LCOV - code coverage report
Current view: top level - libreoffice/tools/source/generic - b3dtrans.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 285 0.0 %
Date: 2012-12-27 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <tools/b3dtrans.hxx>
      21             : 
      22             : // B3dTransformationSet --------------------------------------------------------
      23             : // Transformations for all 3D output
      24             : 
      25           0 : B3dTransformationSet::B3dTransformationSet()
      26             : {
      27           0 :     Reset();
      28           0 : }
      29             : 
      30           0 : B3dTransformationSet::~B3dTransformationSet()
      31             : {
      32           0 : }
      33             : 
      34           0 : void B3dTransformationSet::Orientation(basegfx::B3DHomMatrix& rTarget, basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
      35             : {
      36           0 :     rTarget.translate( -aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
      37           0 :     aVUP.normalize();
      38           0 :     aVPN.normalize();
      39           0 :     basegfx::B3DVector aRx(aVUP);
      40           0 :     basegfx::B3DVector aRy(aVPN);
      41           0 :     aRx = aRx.getPerpendicular(aRy);
      42           0 :     aRx.normalize();
      43           0 :     aRy = aRy.getPerpendicular(aRx);
      44           0 :     aRy.normalize();
      45           0 :     basegfx::B3DHomMatrix aTemp;
      46           0 :     aTemp.set(0, 0, aRx.getX());
      47           0 :     aTemp.set(0, 1, aRx.getY());
      48           0 :     aTemp.set(0, 2, aRx.getZ());
      49           0 :     aTemp.set(1, 0, aRy.getX());
      50           0 :     aTemp.set(1, 1, aRy.getY());
      51           0 :     aTemp.set(1, 2, aRy.getZ());
      52           0 :     aTemp.set(2, 0, aVPN.getX());
      53           0 :     aTemp.set(2, 1, aVPN.getY());
      54           0 :     aTemp.set(2, 2, aVPN.getZ());
      55           0 :     rTarget *= aTemp;
      56           0 : }
      57             : 
      58           0 : void B3dTransformationSet::Frustum(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
      59             : {
      60           0 :     if(!(fNear > 0.0))
      61             :     {
      62           0 :         fNear = 0.001;
      63             :     }
      64           0 :     if(!(fFar > 0.0))
      65             :     {
      66           0 :         fFar = 1.0;
      67             :     }
      68           0 :     if(fNear == fFar)
      69             :     {
      70           0 :         fFar = fNear + 1.0;
      71             :     }
      72           0 :     if(fLeft == fRight)
      73             :     {
      74           0 :         fLeft -= 1.0;
      75           0 :         fRight += 1.0;
      76             :     }
      77           0 :     if(fTop == fBottom)
      78             :     {
      79           0 :         fBottom -= 1.0;
      80           0 :         fTop += 1.0;
      81             :     }
      82           0 :     basegfx::B3DHomMatrix aTemp;
      83             : 
      84           0 :     aTemp.set(0, 0, 2.0 * fNear / (fRight - fLeft));
      85           0 :     aTemp.set(1, 1, 2.0 * fNear / (fTop - fBottom));
      86           0 :     aTemp.set(0, 2, (fRight + fLeft) / (fRight - fLeft));
      87           0 :     aTemp.set(1, 2, (fTop + fBottom) / (fTop - fBottom));
      88           0 :     aTemp.set(2, 2, -1.0 * ((fFar + fNear) / (fFar - fNear)));
      89           0 :     aTemp.set(3, 2, -1.0);
      90           0 :     aTemp.set(2, 3, -1.0 * ((2.0 * fFar * fNear) / (fFar - fNear)));
      91           0 :     aTemp.set(3, 3, 0.0);
      92             : 
      93           0 :     rTarget *= aTemp;
      94           0 : }
      95             : 
      96           0 : void B3dTransformationSet::Ortho(basegfx::B3DHomMatrix& rTarget,
      97             :                                  double fLeft, double fRight, double fBottom, double fTop,
      98             :                                  double fNear, double fFar)
      99             : {
     100           0 :     if(fNear == fFar)
     101             :     {
     102             :         OSL_FAIL("Near and far clipping plane in Ortho definition are identical");
     103           0 :         fFar = fNear + 1.0;
     104             :     }
     105           0 :     if(fLeft == fRight)
     106             :     {
     107             :         OSL_FAIL("Left and right in Ortho definition are identical");
     108           0 :         fLeft -= 1.0;
     109           0 :         fRight += 1.0;
     110             :     }
     111           0 :     if(fTop == fBottom)
     112             :     {
     113             :         OSL_FAIL("Top and bottom in Ortho definition are identical");
     114           0 :         fBottom -= 1.0;
     115           0 :         fTop += 1.0;
     116             :     }
     117           0 :     basegfx::B3DHomMatrix aTemp;
     118             : 
     119           0 :     aTemp.set(0, 0, 2.0 / (fRight - fLeft));
     120           0 :     aTemp.set(1, 1, 2.0 / (fTop - fBottom));
     121           0 :     aTemp.set(2, 2, -1.0 * (2.0 / (fFar - fNear)));
     122           0 :     aTemp.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft)));
     123           0 :     aTemp.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom)));
     124           0 :     aTemp.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear)));
     125             : 
     126           0 :     rTarget *= aTemp;
     127           0 : }
     128             : 
     129             : /// reset values
     130           0 : void B3dTransformationSet::Reset()
     131             : {
     132             :     // Reset matrices to identity matrices
     133           0 :     maObjectTrans.identity();
     134           0 :     PostSetObjectTrans();
     135             : 
     136           0 :     Orientation(maOrientation);
     137           0 :     PostSetOrientation();
     138             : 
     139           0 :     maTexture.identity();
     140             : 
     141           0 :     mfLeftBound = mfBottomBound = -1.0;
     142           0 :     mfRightBound = mfTopBound = 1.0;
     143           0 :     mfNearBound = 0.001;
     144           0 :     mfFarBound = 1.001;
     145             : 
     146           0 :     meRatio = Base3DRatioGrow;
     147           0 :     mfRatio = 0.0;
     148             : 
     149           0 :     maViewportRectangle = Rectangle(-1, -1, 2, 2);
     150           0 :     maVisibleRectangle = maViewportRectangle;
     151             : 
     152           0 :     mbPerspective = sal_True;
     153             : 
     154           0 :     mbProjectionValid = sal_False;
     155           0 :     mbObjectToDeviceValid = sal_False;
     156           0 :     mbWorldToViewValid = sal_False;
     157             : 
     158           0 :     CalcViewport();
     159           0 : }
     160             : 
     161             : /// Object transformation
     162           0 : void B3dTransformationSet::PostSetObjectTrans()
     163             : {
     164             :     // Assign and compute inverse
     165           0 :     maInvObjectTrans = maObjectTrans;
     166           0 :     maInvObjectTrans.invert();
     167           0 : }
     168             : 
     169           0 : void B3dTransformationSet::SetOrientation( basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
     170             : {
     171           0 :     maOrientation.identity();
     172           0 :     Orientation(maOrientation, aVRP, aVPN, aVUP);
     173             : 
     174           0 :     mbInvTransObjectToEyeValid = sal_False;
     175           0 :     mbObjectToDeviceValid = sal_False;
     176           0 :     mbWorldToViewValid = sal_False;
     177             : 
     178           0 :     PostSetOrientation();
     179           0 : }
     180             : 
     181           0 : void B3dTransformationSet::PostSetOrientation()
     182             : {
     183             :     // Assign and compute inverse
     184           0 :     maInvOrientation = maOrientation;
     185           0 :     maInvOrientation.invert();
     186           0 : }
     187             : 
     188             : /// Projections for transformations
     189           0 : void B3dTransformationSet::SetProjection(const basegfx::B3DHomMatrix& mProject)
     190             : {
     191           0 :     maProjection = mProject;
     192           0 :     PostSetProjection();
     193           0 : }
     194             : 
     195           0 : const basegfx::B3DHomMatrix& B3dTransformationSet::GetProjection()
     196             : {
     197           0 :     if(!mbProjectionValid)
     198           0 :         CalcViewport();
     199           0 :     return maProjection;
     200             : }
     201             : 
     202           0 : void B3dTransformationSet::PostSetProjection()
     203             : {
     204             :     // Assign and comptue inverse
     205           0 :     maInvProjection = GetProjection();
     206           0 :     maInvProjection.invert();
     207             : 
     208             :     // invalidate dependent matrices
     209           0 :     mbObjectToDeviceValid = sal_False;
     210           0 :     mbWorldToViewValid = sal_False;
     211           0 : }
     212             : 
     213             : /// Transformations for viewport
     214           0 : void B3dTransformationSet::CalcViewport()
     215             : {
     216             :     // Parameters for projection
     217           0 :     double fLeft(mfLeftBound);
     218           0 :     double fRight(mfRightBound);
     219           0 :     double fBottom(mfBottomBound);
     220           0 :     double fTop(mfTopBound);
     221             : 
     222             :     // Adjust projection to aspect ratio, if set
     223           0 :     if(GetRatio() != 0.0)
     224             :     {
     225             :         // Compute current aspect ratio of boundaries
     226           0 :         double fBoundWidth = (double)(maViewportRectangle.GetWidth() + 1);
     227           0 :         double fBoundHeight = (double)(maViewportRectangle.GetHeight() + 1);
     228           0 :         double fActRatio = 1;
     229             :         double fFactor;
     230             : 
     231           0 :         if(fBoundWidth != 0.0)
     232           0 :             fActRatio = fBoundHeight / fBoundWidth;
     233             :         // FIXME   else in this case has a lot of problems,  should this return.
     234             : 
     235           0 :         switch(meRatio)
     236             :         {
     237             :             case Base3DRatioShrink :
     238             :             {
     239             :                 // Dilate smaller part
     240           0 :                 if(fActRatio > mfRatio)
     241             :                 {
     242             :                     // enlarge X
     243           0 :                     fFactor = 1.0 / fActRatio;
     244           0 :                     fRight  *= fFactor;
     245           0 :                     fLeft *= fFactor;
     246             :                 }
     247             :                 else
     248             :                 {
     249             :                     // enlarge Y
     250           0 :                     fFactor = fActRatio;
     251           0 :                     fTop *= fFactor;
     252           0 :                     fBottom *= fFactor;
     253             :                 }
     254           0 :                 break;
     255             :             }
     256             :             case Base3DRatioGrow :
     257             :             {
     258             :                 // scale down larger part
     259           0 :                 if(fActRatio > mfRatio)
     260             :                 {
     261             :                     // scale down Y
     262           0 :                     fFactor = fActRatio;
     263           0 :                     fTop *= fFactor;
     264           0 :                     fBottom *= fFactor;
     265             :                 }
     266             :                 else
     267             :                 {
     268             :                     // scale down X
     269           0 :                     fFactor = 1.0 / fActRatio;
     270           0 :                     fRight  *= fFactor;
     271           0 :                     fLeft *= fFactor;
     272             :                 }
     273           0 :                 break;
     274             :             }
     275             :             case Base3DRatioMiddle :
     276             :             {
     277             :                 // averaging
     278           0 :                 fFactor = ((1.0 / fActRatio) + 1.0) / 2.0;
     279           0 :                 fRight *= fFactor;
     280           0 :                 fLeft *= fFactor;
     281           0 :                 fFactor = (fActRatio + 1.0) / 2.0;
     282           0 :                 fTop *= fFactor;
     283           0 :                 fBottom *= fFactor;
     284           0 :                 break;
     285             :             }
     286             :         }
     287             :     }
     288             : 
     289             :     // Do projection and object areas overlap?
     290           0 :     maSetBound = maViewportRectangle;
     291             : 
     292             :     // Reset projection with new values
     293           0 :     basegfx::B3DHomMatrix aNewProjection;
     294             : 
     295             :     // #i36281#
     296             :     // OpenGL needs a little more rough additional size to not let
     297             :     // the front face vanish. Changed from SMALL_DVALUE to 0.000001,
     298             :     // which is 1/10000th, comared with 1/tenth of a million from SMALL_DVALUE.
     299           0 :     const double fDistPart((mfFarBound - mfNearBound) * 0.0001);
     300             : 
     301             :     // To avoid critical clipping, set Near & Far generously
     302           0 :     if(mbPerspective)
     303             :     {
     304           0 :         Frustum(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
     305             :     }
     306             :     else
     307             :     {
     308           0 :         Ortho(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
     309             :     }
     310             : 
     311             :     // Set to true to guarantee loop termination
     312           0 :     mbProjectionValid = sal_True;
     313             : 
     314             :     // set new projection
     315           0 :     SetProjection(aNewProjection);
     316             : 
     317             :     // fill parameters for ViewportTransformation
     318             :     // Translation
     319           0 :     maTranslate.setX((double)maSetBound.Left() + ((maSetBound.GetWidth() - 1L) / 2.0));
     320           0 :     maTranslate.setY((double)maSetBound.Top() + ((maSetBound.GetHeight() - 1L) / 2.0));
     321           0 :     maTranslate.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
     322             : 
     323             :     // Scaling
     324           0 :     maScale.setX((maSetBound.GetWidth() - 1L) / 2.0);
     325           0 :     maScale.setY((maSetBound.GetHeight() - 1L) / -2.0);
     326           0 :     maScale.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
     327             : 
     328             :     // React to change of viewport
     329           0 :     PostSetViewport();
     330           0 : }
     331             : 
     332           0 : void B3dTransformationSet::SetRatio(double fNew)
     333             : {
     334           0 :     if(mfRatio != fNew)
     335             :     {
     336           0 :         mfRatio = fNew;
     337           0 :         mbProjectionValid = sal_False;
     338           0 :         mbObjectToDeviceValid = sal_False;
     339           0 :         mbWorldToViewValid = sal_False;
     340             :     }
     341           0 : }
     342             : 
     343           0 : void B3dTransformationSet::SetDeviceRectangle(double fL, double fR, double fB, double fT,
     344             :     sal_Bool bBroadCastChange)
     345             : {
     346           0 :     if(fL != mfLeftBound || fR != mfRightBound || fB != mfBottomBound || fT != mfTopBound)
     347             :     {
     348           0 :         mfLeftBound = fL;
     349           0 :         mfRightBound = fR;
     350           0 :         mfBottomBound = fB;
     351           0 :         mfTopBound = fT;
     352             : 
     353           0 :         mbProjectionValid = sal_False;
     354           0 :         mbObjectToDeviceValid = sal_False;
     355           0 :         mbWorldToViewValid = sal_False;
     356             : 
     357             :         // Broadcast changes
     358           0 :         if(bBroadCastChange)
     359           0 :             DeviceRectangleChange();
     360             :     }
     361           0 : }
     362             : 
     363           0 : void B3dTransformationSet::DeviceRectangleChange()
     364             : {
     365           0 : }
     366             : 
     367           0 : void B3dTransformationSet::SetPerspective(sal_Bool bNew)
     368             : {
     369           0 :     if(mbPerspective != bNew)
     370             :     {
     371           0 :         mbPerspective = bNew;
     372           0 :         mbProjectionValid = sal_False;
     373           0 :         mbObjectToDeviceValid = sal_False;
     374           0 :         mbWorldToViewValid = sal_False;
     375             :     }
     376           0 : }
     377             : 
     378           0 : void B3dTransformationSet::SetViewportRectangle(Rectangle& rRect, Rectangle& rVisible)
     379             : {
     380           0 :     if(rRect != maViewportRectangle || rVisible != maVisibleRectangle)
     381             :     {
     382           0 :         maViewportRectangle = rRect;
     383           0 :         maVisibleRectangle = rVisible;
     384             : 
     385           0 :         mbProjectionValid = sal_False;
     386           0 :         mbObjectToDeviceValid = sal_False;
     387           0 :         mbWorldToViewValid = sal_False;
     388             :     }
     389           0 : }
     390             : 
     391           0 : void B3dTransformationSet::PostSetViewport()
     392             : {
     393           0 : }
     394             : 
     395             : // direct access to various transformations
     396             : 
     397           0 : const basegfx::B3DPoint B3dTransformationSet::WorldToEyeCoor(const basegfx::B3DPoint& rVec)
     398             : {
     399           0 :     basegfx::B3DPoint aVec(rVec);
     400           0 :     aVec *= GetOrientation();
     401           0 :     return aVec;
     402             : }
     403             : 
     404           0 : const basegfx::B3DPoint B3dTransformationSet::EyeToWorldCoor(const basegfx::B3DPoint& rVec)
     405             : {
     406           0 :     basegfx::B3DPoint aVec(rVec);
     407           0 :     aVec *= GetInvOrientation();
     408           0 :     return aVec;
     409             : }
     410             : 
     411             : // B3dViewport -----------------------------------------------------------------
     412             : 
     413           0 : B3dViewport::B3dViewport()
     414             : :   B3dTransformationSet(),
     415             :     aVRP(0, 0, 0),
     416             :     aVPN(0, 0, 1),
     417           0 :     aVUV(0, 1, 0)
     418             : {
     419           0 :     CalcOrientation();
     420           0 : }
     421             : 
     422           0 : B3dViewport::~B3dViewport()
     423             : {
     424           0 : }
     425             : 
     426           0 : void B3dViewport::SetVUV(const basegfx::B3DVector& rNewVUV)
     427             : {
     428           0 :     aVUV = rNewVUV;
     429           0 :     CalcOrientation();
     430           0 : }
     431             : 
     432           0 : void B3dViewport::SetViewportValues(
     433             :     const basegfx::B3DPoint& rNewVRP,
     434             :     const basegfx::B3DVector& rNewVPN,
     435             :     const basegfx::B3DVector& rNewVUV)
     436             : {
     437           0 :     aVRP = rNewVRP;
     438           0 :     aVPN = rNewVPN;
     439           0 :     aVUV = rNewVUV;
     440           0 :     CalcOrientation();
     441           0 : }
     442             : 
     443           0 : void B3dViewport::CalcOrientation()
     444             : {
     445           0 :     SetOrientation(aVRP, aVPN, aVUV);
     446           0 : }
     447             : 
     448             : // B3dCamera -------------------------------------------------------------------
     449             : 
     450           0 : B3dCamera::B3dCamera(
     451             :     const basegfx::B3DPoint& rPos, const basegfx::B3DVector& rLkAt,
     452             :     double fFocLen, double fBnkAng, sal_Bool bUseFocLen)
     453             : :   B3dViewport(),
     454             :     aPosition(rPos),
     455             :     aCorrectedPosition(rPos),
     456             :     aLookAt(rLkAt),
     457             :     fFocalLength(fFocLen),
     458             :     fBankAngle(fBnkAng),
     459           0 :     bUseFocalLength(bUseFocLen)
     460             : {
     461           0 :     CalcNewViewportValues();
     462           0 : }
     463             : 
     464           0 : B3dCamera::~B3dCamera()
     465             : {
     466           0 : }
     467             : 
     468           0 : void B3dCamera::DeviceRectangleChange()
     469             : {
     470             :     // call parent
     471           0 :     B3dViewport::DeviceRectangleChange();
     472             : 
     473             :     // react to changes
     474           0 :     CalcNewViewportValues();
     475           0 : }
     476             : 
     477           0 : void B3dCamera::CalcNewViewportValues()
     478             : {
     479           0 :     basegfx::B3DVector aViewVector(aPosition - aLookAt);
     480           0 :     basegfx::B3DVector aNewVPN(aViewVector);
     481             : 
     482           0 :     basegfx::B3DVector aNewVUV(0.0, 1.0, 0.0);
     483           0 :     if(aNewVPN.getLength() < aNewVPN.getY())
     484           0 :         aNewVUV.setX(0.5);
     485             : 
     486           0 :     aNewVUV.normalize();
     487           0 :     aNewVPN.normalize();
     488             : 
     489           0 :     basegfx::B3DVector aNewToTheRight = aNewVPN;
     490           0 :     aNewToTheRight = aNewToTheRight.getPerpendicular(aNewVUV);
     491           0 :     aNewToTheRight.normalize();
     492           0 :     aNewVUV = aNewToTheRight.getPerpendicular(aNewVPN);
     493           0 :     aNewVUV.normalize();
     494             : 
     495           0 :     SetViewportValues(aPosition, aNewVPN, aNewVUV);
     496           0 :     if(CalcFocalLength())
     497           0 :         SetViewportValues(aCorrectedPosition, aNewVPN, aNewVUV);
     498             : 
     499           0 :     if(fBankAngle != 0.0)
     500             :     {
     501           0 :         basegfx::B3DHomMatrix aRotMat;
     502           0 :         aRotMat.rotate(0.0, 0.0, fBankAngle);
     503           0 :         basegfx::B3DVector aUp(0.0, 1.0, 0.0);
     504           0 :         aUp *= aRotMat;
     505           0 :         aUp = EyeToWorldCoor(aUp);
     506           0 :         aUp.normalize();
     507           0 :         SetVUV(aUp);
     508           0 :     }
     509           0 : }
     510             : 
     511           0 : sal_Bool B3dCamera::CalcFocalLength()
     512             : {
     513           0 :     double fWidth = GetDeviceRectangleWidth();
     514           0 :     sal_Bool bRetval = sal_False;
     515             : 
     516           0 :     if(bUseFocalLength)
     517             :     {
     518             :         // Update position if focal length changes
     519           0 :         aCorrectedPosition = basegfx::B3DPoint(0.0, 0.0, fFocalLength * fWidth / 35.0);
     520           0 :         aCorrectedPosition = EyeToWorldCoor(aCorrectedPosition);
     521           0 :         bRetval = sal_True;
     522             :     }
     523             :     else
     524             :     {
     525             :         // Adjust focal length based on given position
     526           0 :         basegfx::B3DPoint aOldPosition;
     527           0 :         aOldPosition = WorldToEyeCoor(aOldPosition);
     528           0 :         if(fWidth != 0.0)
     529           0 :             fFocalLength = aOldPosition.getZ() / fWidth * 35.0;
     530           0 :         if(fFocalLength < 5.0)
     531           0 :             fFocalLength = 5.0;
     532             :     }
     533           0 :     return bRetval;
     534             : }
     535             : 
     536             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10