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

Generated by: LCOV version 1.11