LCOV - code coverage report
Current view: top level - tools/source/generic - b3dtrans.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 205 285 71.9 %
Date: 2014-11-03 Functions: 28 34 82.4 %
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        1406 : B3dTransformationSet::B3dTransformationSet()
      26             : {
      27        1406 :     Reset();
      28        1406 : }
      29             : 
      30        1406 : B3dTransformationSet::~B3dTransformationSet()
      31             : {
      32        1406 : }
      33             : 
      34        7083 : void B3dTransformationSet::Orientation(basegfx::B3DHomMatrix& rTarget, basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
      35             : {
      36        7083 :     rTarget.translate( -aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
      37        7083 :     aVUP.normalize();
      38        7083 :     aVPN.normalize();
      39        7083 :     basegfx::B3DVector aRx(aVUP);
      40       14166 :     basegfx::B3DVector aRy(aVPN);
      41        7083 :     aRx = aRx.getPerpendicular(aRy);
      42        7083 :     aRx.normalize();
      43        7083 :     aRy = aRy.getPerpendicular(aRx);
      44        7083 :     aRy.normalize();
      45       14166 :     basegfx::B3DHomMatrix aTemp;
      46        7083 :     aTemp.set(0, 0, aRx.getX());
      47        7083 :     aTemp.set(0, 1, aRx.getY());
      48        7083 :     aTemp.set(0, 2, aRx.getZ());
      49        7083 :     aTemp.set(1, 0, aRy.getX());
      50        7083 :     aTemp.set(1, 1, aRy.getY());
      51        7083 :     aTemp.set(1, 2, aRy.getZ());
      52        7083 :     aTemp.set(2, 0, aVPN.getX());
      53        7083 :     aTemp.set(2, 1, aVPN.getY());
      54        7083 :     aTemp.set(2, 2, aVPN.getZ());
      55       14166 :     rTarget *= aTemp;
      56        7083 : }
      57             : 
      58        1406 : void B3dTransformationSet::Frustum(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
      59             : {
      60        1406 :     if(!(fNear > 0.0))
      61             :     {
      62           0 :         fNear = 0.001;
      63             :     }
      64        1406 :     if(!(fFar > 0.0))
      65             :     {
      66           0 :         fFar = 1.0;
      67             :     }
      68        1406 :     if(fNear == fFar)
      69             :     {
      70           0 :         fFar = fNear + 1.0;
      71             :     }
      72        1406 :     if(fLeft == fRight)
      73             :     {
      74           0 :         fLeft -= 1.0;
      75           0 :         fRight += 1.0;
      76             :     }
      77        1406 :     if(fTop == fBottom)
      78             :     {
      79           0 :         fBottom -= 1.0;
      80           0 :         fTop += 1.0;
      81             :     }
      82        1406 :     basegfx::B3DHomMatrix aTemp;
      83             : 
      84        1406 :     aTemp.set(0, 0, 2.0 * fNear / (fRight - fLeft));
      85        1406 :     aTemp.set(1, 1, 2.0 * fNear / (fTop - fBottom));
      86        1406 :     aTemp.set(0, 2, (fRight + fLeft) / (fRight - fLeft));
      87        1406 :     aTemp.set(1, 2, (fTop + fBottom) / (fTop - fBottom));
      88        1406 :     aTemp.set(2, 2, -1.0 * ((fFar + fNear) / (fFar - fNear)));
      89        1406 :     aTemp.set(3, 2, -1.0);
      90        1406 :     aTemp.set(2, 3, -1.0 * ((2.0 * fFar * fNear) / (fFar - fNear)));
      91        1406 :     aTemp.set(3, 3, 0.0);
      92             : 
      93        1406 :     rTarget *= aTemp;
      94        1406 : }
      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        1406 : void B3dTransformationSet::Reset()
     131             : {
     132             :     // Reset matrices to identity matrices
     133        1406 :     maObjectTrans.identity();
     134        1406 :     PostSetObjectTrans();
     135             : 
     136        1406 :     Orientation(maOrientation);
     137        1406 :     PostSetOrientation();
     138             : 
     139        1406 :     maTexture.identity();
     140             : 
     141        1406 :     mfLeftBound = mfBottomBound = -1.0;
     142        1406 :     mfRightBound = mfTopBound = 1.0;
     143        1406 :     mfNearBound = 0.001;
     144        1406 :     mfFarBound = 1.001;
     145             : 
     146        1406 :     meRatio = Base3DRatioGrow;
     147        1406 :     mfRatio = 0.0;
     148             : 
     149        1406 :     maViewportRectangle = Rectangle(-1, -1, 2, 2);
     150        1406 :     maVisibleRectangle = maViewportRectangle;
     151             : 
     152        1406 :     mbPerspective = true;
     153             : 
     154        1406 :     mbProjectionValid = false;
     155        1406 :     mbObjectToDeviceValid = false;
     156        1406 :     mbWorldToViewValid = false;
     157             : 
     158        1406 :     CalcViewport();
     159        1406 : }
     160             : 
     161             : /// Object transformation
     162        1406 : void B3dTransformationSet::PostSetObjectTrans()
     163             : {
     164             :     // Assign and compute inverse
     165        1406 :     maInvObjectTrans = maObjectTrans;
     166        1406 :     maInvObjectTrans.invert();
     167        1406 : }
     168             : 
     169        5677 : void B3dTransformationSet::SetOrientation( basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
     170             : {
     171        5677 :     maOrientation.identity();
     172        5677 :     Orientation(maOrientation, aVRP, aVPN, aVUP);
     173             : 
     174        5677 :     mbInvTransObjectToEyeValid = false;
     175        5677 :     mbObjectToDeviceValid = false;
     176        5677 :     mbWorldToViewValid = false;
     177             : 
     178        5677 :     PostSetOrientation();
     179        5677 : }
     180             : 
     181        7083 : void B3dTransformationSet::PostSetOrientation()
     182             : {
     183             :     // Assign and compute inverse
     184        7083 :     maInvOrientation = maOrientation;
     185        7083 :     maInvOrientation.invert();
     186        7083 : }
     187             : 
     188             : /// Projections for transformations
     189        1406 : void B3dTransformationSet::SetProjection(const basegfx::B3DHomMatrix& mProject)
     190             : {
     191        1406 :     maProjection = mProject;
     192        1406 :     PostSetProjection();
     193        1406 : }
     194             : 
     195        1406 : const basegfx::B3DHomMatrix& B3dTransformationSet::GetProjection()
     196             : {
     197        1406 :     if(!mbProjectionValid)
     198           0 :         CalcViewport();
     199        1406 :     return maProjection;
     200             : }
     201             : 
     202        1406 : void B3dTransformationSet::PostSetProjection()
     203             : {
     204             :     // Assign and comptue inverse
     205        1406 :     maInvProjection = GetProjection();
     206        1406 :     maInvProjection.invert();
     207             : 
     208             :     // invalidate dependent matrices
     209        1406 :     mbObjectToDeviceValid = false;
     210        1406 :     mbWorldToViewValid = false;
     211        1406 : }
     212             : 
     213             : /// Transformations for viewport
     214        1406 : void B3dTransformationSet::CalcViewport()
     215             : {
     216             :     // Parameters for projection
     217        1406 :     double fLeft(mfLeftBound);
     218        1406 :     double fRight(mfRightBound);
     219        1406 :     double fBottom(mfBottomBound);
     220        1406 :     double fTop(mfTopBound);
     221             : 
     222             :     // Adjust projection to aspect ratio, if set
     223        1406 :     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        1406 :     maSetBound = maViewportRectangle;
     291             : 
     292             :     // Reset projection with new values
     293        1406 :     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        1406 :     const double fDistPart((mfFarBound - mfNearBound) * 0.0001);
     300             : 
     301             :     // To avoid critical clipping, set Near & Far generously
     302        1406 :     if(mbPerspective)
     303             :     {
     304        1406 :         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        1406 :     mbProjectionValid = true;
     313             : 
     314             :     // set new projection
     315        1406 :     SetProjection(aNewProjection);
     316             : 
     317             :     // fill parameters for ViewportTransformation
     318             :     // Translation
     319        1406 :     maTranslate.setX((double)maSetBound.Left() + ((maSetBound.GetWidth() - 1L) / 2.0));
     320        1406 :     maTranslate.setY((double)maSetBound.Top() + ((maSetBound.GetHeight() - 1L) / 2.0));
     321        1406 :     maTranslate.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
     322             : 
     323             :     // Scaling
     324        1406 :     maScale.setX((maSetBound.GetWidth() - 1L) / 2.0);
     325        1406 :     maScale.setY((maSetBound.GetHeight() - 1L) / -2.0);
     326        1406 :     maScale.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
     327             : 
     328             :     // React to change of viewport
     329        1406 :     PostSetViewport();
     330        1406 : }
     331             : 
     332        1459 : void B3dTransformationSet::SetRatio(double fNew)
     333             : {
     334        1459 :     if(mfRatio != fNew)
     335             :     {
     336           0 :         mfRatio = fNew;
     337           0 :         mbProjectionValid = false;
     338           0 :         mbObjectToDeviceValid = false;
     339           0 :         mbWorldToViewValid = false;
     340             :     }
     341        1459 : }
     342             : 
     343        1406 : void B3dTransformationSet::SetDeviceRectangle(double fL, double fR, double fB, double fT,
     344             :                                               bool bBroadCastChange)
     345             : {
     346        1406 :     if(fL != mfLeftBound || fR != mfRightBound || fB != mfBottomBound || fT != mfTopBound)
     347             :     {
     348        1406 :         mfLeftBound = fL;
     349        1406 :         mfRightBound = fR;
     350        1406 :         mfBottomBound = fB;
     351        1406 :         mfTopBound = fT;
     352             : 
     353        1406 :         mbProjectionValid = false;
     354        1406 :         mbObjectToDeviceValid = false;
     355        1406 :         mbWorldToViewValid = false;
     356             : 
     357             :         // Broadcast changes
     358        1406 :         if(bBroadCastChange)
     359        1406 :             DeviceRectangleChange();
     360             :     }
     361        1406 : }
     362             : 
     363        1406 : void B3dTransformationSet::DeviceRectangleChange()
     364             : {
     365        1406 : }
     366             : 
     367        1459 : void B3dTransformationSet::SetPerspective(bool bNew)
     368             : {
     369        1459 :     if(mbPerspective != bNew)
     370             :     {
     371          16 :         mbPerspective = bNew;
     372          16 :         mbProjectionValid = false;
     373          16 :         mbObjectToDeviceValid = false;
     374          16 :         mbWorldToViewValid = false;
     375             :     }
     376        1459 : }
     377             : 
     378        6152 : void B3dTransformationSet::SetViewportRectangle(Rectangle& rRect, Rectangle& rVisible)
     379             : {
     380        6152 :     if(rRect != maViewportRectangle || rVisible != maVisibleRectangle)
     381             :     {
     382        3287 :         maViewportRectangle = rRect;
     383        3287 :         maVisibleRectangle = rVisible;
     384             : 
     385        3287 :         mbProjectionValid = false;
     386        3287 :         mbObjectToDeviceValid = false;
     387        3287 :         mbWorldToViewValid = false;
     388             :     }
     389        6152 : }
     390             : 
     391        1406 : void B3dTransformationSet::PostSetViewport()
     392             : {
     393        1406 : }
     394             : 
     395             : // direct access to various transformations
     396             : 
     397        2812 : const basegfx::B3DPoint B3dTransformationSet::WorldToEyeCoor(const basegfx::B3DPoint& rVec)
     398             : {
     399        2812 :     basegfx::B3DPoint aVec(rVec);
     400        2812 :     aVec *= GetOrientation();
     401        2812 :     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        1406 : B3dViewport::B3dViewport()
     414             : :   B3dTransformationSet(),
     415             :     aVRP(0, 0, 0),
     416             :     aVPN(0, 0, 1),
     417        1406 :     aVUV(0, 1, 0)
     418             : {
     419        1406 :     CalcOrientation();
     420        1406 : }
     421             : 
     422        1406 : B3dViewport::~B3dViewport()
     423             : {
     424        1406 : }
     425             : 
     426           0 : void B3dViewport::SetVUV(const basegfx::B3DVector& rNewVUV)
     427             : {
     428           0 :     aVUV = rNewVUV;
     429           0 :     CalcOrientation();
     430           0 : }
     431             : 
     432        4271 : void B3dViewport::SetViewportValues(
     433             :     const basegfx::B3DPoint& rNewVRP,
     434             :     const basegfx::B3DVector& rNewVPN,
     435             :     const basegfx::B3DVector& rNewVUV)
     436             : {
     437        4271 :     aVRP = rNewVRP;
     438        4271 :     aVPN = rNewVPN;
     439        4271 :     aVUV = rNewVUV;
     440        4271 :     CalcOrientation();
     441        4271 : }
     442             : 
     443        5677 : void B3dViewport::CalcOrientation()
     444             : {
     445        5677 :     SetOrientation(aVRP, aVPN, aVUV);
     446        5677 : }
     447             : 
     448             : // B3dCamera -------------------------------------------------------------------
     449             : 
     450        1406 : B3dCamera::B3dCamera(
     451             :     const basegfx::B3DPoint& rPos, const basegfx::B3DVector& rLkAt,
     452             :     double fFocLen, double fBnkAng, bool bUseFocLen)
     453             : :   B3dViewport(),
     454             :     aPosition(rPos),
     455             :     aCorrectedPosition(rPos),
     456             :     aLookAt(rLkAt),
     457             :     fFocalLength(fFocLen),
     458             :     fBankAngle(fBnkAng),
     459        1406 :     bUseFocalLength(bUseFocLen)
     460             : {
     461        1406 :     CalcNewViewportValues();
     462        1406 : }
     463             : 
     464        1406 : B3dCamera::~B3dCamera()
     465             : {
     466        1406 : }
     467             : 
     468        1406 : void B3dCamera::DeviceRectangleChange()
     469             : {
     470             :     // call parent
     471        1406 :     B3dViewport::DeviceRectangleChange();
     472             : 
     473             :     // react to changes
     474        1406 :     CalcNewViewportValues();
     475        1406 : }
     476             : 
     477        2812 : void B3dCamera::CalcNewViewportValues()
     478             : {
     479        2812 :     basegfx::B3DVector aViewVector(aPosition - aLookAt);
     480        5624 :     basegfx::B3DVector aNewVPN(aViewVector);
     481             : 
     482        5624 :     basegfx::B3DVector aNewVUV(0.0, 1.0, 0.0);
     483        2812 :     if(aNewVPN.getLength() < aNewVPN.getY())
     484           0 :         aNewVUV.setX(0.5);
     485             : 
     486        2812 :     aNewVUV.normalize();
     487        2812 :     aNewVPN.normalize();
     488             : 
     489        5624 :     basegfx::B3DVector aNewToTheRight = aNewVPN;
     490        2812 :     aNewToTheRight = aNewToTheRight.getPerpendicular(aNewVUV);
     491        2812 :     aNewToTheRight.normalize();
     492        2812 :     aNewVUV = aNewToTheRight.getPerpendicular(aNewVPN);
     493        2812 :     aNewVUV.normalize();
     494             : 
     495        2812 :     SetViewportValues(aPosition, aNewVPN, aNewVUV);
     496        2812 :     if(CalcFocalLength())
     497           0 :         SetViewportValues(aCorrectedPosition, aNewVPN, aNewVUV);
     498             : 
     499        2812 :     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        2812 :     }
     509        2812 : }
     510             : 
     511        2812 : bool B3dCamera::CalcFocalLength()
     512             : {
     513        2812 :     double fWidth = GetDeviceRectangleWidth();
     514        2812 :     bool bRetval = false;
     515             : 
     516        2812 :     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 = true;
     522             :     }
     523             :     else
     524             :     {
     525             :         // Adjust focal length based on given position
     526        2812 :         basegfx::B3DPoint aOldPosition;
     527        2812 :         aOldPosition = WorldToEyeCoor(aOldPosition);
     528        2812 :         if(fWidth != 0.0)
     529        2812 :             fFocalLength = aOldPosition.getZ() / fWidth * 35.0;
     530        2812 :         if(fFocalLength < 5.0)
     531        2812 :             fFocalLength = 5.0;
     532             :     }
     533        2812 :     return bRetval;
     534             : }
     535             : 
     536             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10