fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / tools / source / generic / b3dtrans.cxx
blobcf27e1844ddc1334fb2d0731fd3aac1ed2643868
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/b3dtrans.hxx>
22 #include <osl/diagnose.h>
24 // B3dTransformationSet --------------------------------------------------------
25 // Transformations for all 3D output
27 B3dTransformationSet::B3dTransformationSet()
29 Reset();
32 B3dTransformationSet::~B3dTransformationSet()
36 void B3dTransformationSet::Orientation(basegfx::B3DHomMatrix& rTarget, basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
38 rTarget.translate( -aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
39 aVUP.normalize();
40 aVPN.normalize();
41 basegfx::B3DVector aRx(aVUP);
42 basegfx::B3DVector aRy(aVPN);
43 aRx = aRx.getPerpendicular(aRy);
44 aRx.normalize();
45 aRy = aRy.getPerpendicular(aRx);
46 aRy.normalize();
47 basegfx::B3DHomMatrix aTemp;
48 aTemp.set(0, 0, aRx.getX());
49 aTemp.set(0, 1, aRx.getY());
50 aTemp.set(0, 2, aRx.getZ());
51 aTemp.set(1, 0, aRy.getX());
52 aTemp.set(1, 1, aRy.getY());
53 aTemp.set(1, 2, aRy.getZ());
54 aTemp.set(2, 0, aVPN.getX());
55 aTemp.set(2, 1, aVPN.getY());
56 aTemp.set(2, 2, aVPN.getZ());
57 rTarget *= aTemp;
60 void B3dTransformationSet::Frustum(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
62 if(!(fNear > 0.0))
64 fNear = 0.001;
66 if(!(fFar > 0.0))
68 fFar = 1.0;
70 if(fNear == fFar)
72 fFar = fNear + 1.0;
74 if(fLeft == fRight)
76 fLeft -= 1.0;
77 fRight += 1.0;
79 if(fTop == fBottom)
81 fBottom -= 1.0;
82 fTop += 1.0;
84 basegfx::B3DHomMatrix aTemp;
86 aTemp.set(0, 0, 2.0 * fNear / (fRight - fLeft));
87 aTemp.set(1, 1, 2.0 * fNear / (fTop - fBottom));
88 aTemp.set(0, 2, (fRight + fLeft) / (fRight - fLeft));
89 aTemp.set(1, 2, (fTop + fBottom) / (fTop - fBottom));
90 aTemp.set(2, 2, -1.0 * ((fFar + fNear) / (fFar - fNear)));
91 aTemp.set(3, 2, -1.0);
92 aTemp.set(2, 3, -1.0 * ((2.0 * fFar * fNear) / (fFar - fNear)));
93 aTemp.set(3, 3, 0.0);
95 rTarget *= aTemp;
98 void B3dTransformationSet::Ortho(basegfx::B3DHomMatrix& rTarget,
99 double fLeft, double fRight, double fBottom, double fTop,
100 double fNear, double fFar)
102 if(fNear == fFar)
104 OSL_FAIL("Near and far clipping plane in Ortho definition are identical");
105 fFar = fNear + 1.0;
107 if(fLeft == fRight)
109 OSL_FAIL("Left and right in Ortho definition are identical");
110 fLeft -= 1.0;
111 fRight += 1.0;
113 if(fTop == fBottom)
115 OSL_FAIL("Top and bottom in Ortho definition are identical");
116 fBottom -= 1.0;
117 fTop += 1.0;
119 basegfx::B3DHomMatrix aTemp;
121 aTemp.set(0, 0, 2.0 / (fRight - fLeft));
122 aTemp.set(1, 1, 2.0 / (fTop - fBottom));
123 aTemp.set(2, 2, -1.0 * (2.0 / (fFar - fNear)));
124 aTemp.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft)));
125 aTemp.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom)));
126 aTemp.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear)));
128 rTarget *= aTemp;
131 /// reset values
132 void B3dTransformationSet::Reset()
134 // Reset matrices to identity matrices
135 maObjectTrans.identity();
136 PostSetObjectTrans();
138 Orientation(maOrientation);
139 PostSetOrientation();
141 maTexture.identity();
143 mfLeftBound = mfBottomBound = -1.0;
144 mfRightBound = mfTopBound = 1.0;
145 mfNearBound = 0.001;
146 mfFarBound = 1.001;
148 meRatio = Base3DRatioGrow;
149 mfRatio = 0.0;
151 maViewportRectangle = Rectangle(-1, -1, 2, 2);
152 maVisibleRectangle = maViewportRectangle;
154 mbPerspective = true;
156 mbProjectionValid = false;
157 mbObjectToDeviceValid = false;
158 mbWorldToViewValid = false;
160 CalcViewport();
163 /// Object transformation
164 void B3dTransformationSet::PostSetObjectTrans()
166 // Assign and compute inverse
167 maInvObjectTrans = maObjectTrans;
168 maInvObjectTrans.invert();
171 void B3dTransformationSet::SetOrientation(const basegfx::B3DPoint& rVRP, const basegfx::B3DVector& rVPN, const basegfx::B3DVector& rVUP)
173 maOrientation.identity();
174 Orientation(maOrientation, rVRP, rVPN, rVUP);
176 mbInvTransObjectToEyeValid = false;
177 mbObjectToDeviceValid = false;
178 mbWorldToViewValid = false;
180 PostSetOrientation();
183 void B3dTransformationSet::PostSetOrientation()
185 // Assign and compute inverse
186 maInvOrientation = maOrientation;
187 maInvOrientation.invert();
190 /// Projections for transformations
191 void B3dTransformationSet::SetProjection(const basegfx::B3DHomMatrix& mProject)
193 maProjection = mProject;
194 PostSetProjection();
197 const basegfx::B3DHomMatrix& B3dTransformationSet::GetProjection()
199 if(!mbProjectionValid)
200 CalcViewport();
201 return maProjection;
204 void B3dTransformationSet::PostSetProjection()
206 // Assign and comptue inverse
207 maInvProjection = GetProjection();
208 maInvProjection.invert();
210 // invalidate dependent matrices
211 mbObjectToDeviceValid = false;
212 mbWorldToViewValid = false;
215 /// Transformations for viewport
216 void B3dTransformationSet::CalcViewport()
218 // Parameters for projection
219 double fLeft(mfLeftBound);
220 double fRight(mfRightBound);
221 double fBottom(mfBottomBound);
222 double fTop(mfTopBound);
224 // Adjust projection to aspect ratio, if set
225 if(GetRatio() != 0.0)
227 // Compute current aspect ratio of boundaries
228 double fBoundWidth = (double)(maViewportRectangle.GetWidth() + 1);
229 double fBoundHeight = (double)(maViewportRectangle.GetHeight() + 1);
230 double fActRatio = 1;
231 double fFactor;
233 if(fBoundWidth != 0.0)
234 fActRatio = fBoundHeight / fBoundWidth;
235 // FIXME else in this case has a lot of problems, should this return.
237 switch(meRatio)
239 case Base3DRatioShrink :
241 // Dilate smaller part
242 if(fActRatio > mfRatio)
244 // enlarge X
245 fFactor = 1.0 / fActRatio;
246 fRight *= fFactor;
247 fLeft *= fFactor;
249 else
251 // enlarge Y
252 fFactor = fActRatio;
253 fTop *= fFactor;
254 fBottom *= fFactor;
256 break;
258 case Base3DRatioGrow :
260 // scale down larger part
261 if(fActRatio > mfRatio)
263 // scale down Y
264 fFactor = fActRatio;
265 fTop *= fFactor;
266 fBottom *= fFactor;
268 else
270 // scale down X
271 fFactor = 1.0 / fActRatio;
272 fRight *= fFactor;
273 fLeft *= fFactor;
275 break;
277 case Base3DRatioMiddle :
279 // averaging
280 fFactor = ((1.0 / fActRatio) + 1.0) / 2.0;
281 fRight *= fFactor;
282 fLeft *= fFactor;
283 fFactor = (fActRatio + 1.0) / 2.0;
284 fTop *= fFactor;
285 fBottom *= fFactor;
286 break;
291 // Do projection and object areas overlap?
292 maSetBound = maViewportRectangle;
294 // Reset projection with new values
295 basegfx::B3DHomMatrix aNewProjection;
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 const double fDistPart((mfFarBound - mfNearBound) * 0.0001);
303 // To avoid critical clipping, set Near & Far generously
304 if(mbPerspective)
306 Frustum(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
308 else
310 Ortho(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
313 // Set to true to guarantee loop termination
314 mbProjectionValid = true;
316 // set new projection
317 SetProjection(aNewProjection);
319 // fill parameters for ViewportTransformation
320 // Translation
321 maTranslate.setX((double)maSetBound.Left() + ((maSetBound.GetWidth() - 1L) / 2.0));
322 maTranslate.setY((double)maSetBound.Top() + ((maSetBound.GetHeight() - 1L) / 2.0));
323 maTranslate.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
325 // Scaling
326 maScale.setX((maSetBound.GetWidth() - 1L) / 2.0);
327 maScale.setY((maSetBound.GetHeight() - 1L) / -2.0);
328 maScale.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
331 void B3dTransformationSet::SetRatio(double fNew)
333 if(mfRatio != fNew)
335 mfRatio = fNew;
336 mbProjectionValid = false;
337 mbObjectToDeviceValid = false;
338 mbWorldToViewValid = false;
342 void B3dTransformationSet::SetDeviceRectangle(double fL, double fR, double fB, double fT,
343 bool bBroadCastChange)
345 if(fL != mfLeftBound || fR != mfRightBound || fB != mfBottomBound || fT != mfTopBound)
347 mfLeftBound = fL;
348 mfRightBound = fR;
349 mfBottomBound = fB;
350 mfTopBound = fT;
352 mbProjectionValid = false;
353 mbObjectToDeviceValid = false;
354 mbWorldToViewValid = false;
356 // Broadcast changes
357 if(bBroadCastChange)
358 DeviceRectangleChange();
362 void B3dTransformationSet::DeviceRectangleChange()
366 void B3dTransformationSet::SetPerspective(bool bNew)
368 if(mbPerspective != bNew)
370 mbPerspective = bNew;
371 mbProjectionValid = false;
372 mbObjectToDeviceValid = false;
373 mbWorldToViewValid = false;
377 void B3dTransformationSet::SetViewportRectangle(Rectangle& rRect, Rectangle& rVisible)
379 if(rRect != maViewportRectangle || rVisible != maVisibleRectangle)
381 maViewportRectangle = rRect;
382 maVisibleRectangle = rVisible;
384 mbProjectionValid = false;
385 mbObjectToDeviceValid = false;
386 mbWorldToViewValid = false;
390 // direct access to various transformations
392 const basegfx::B3DPoint B3dTransformationSet::WorldToEyeCoor(const basegfx::B3DPoint& rVec)
394 basegfx::B3DPoint aVec(rVec);
395 aVec *= GetOrientation();
396 return aVec;
399 const basegfx::B3DPoint B3dTransformationSet::EyeToWorldCoor(const basegfx::B3DPoint& rVec)
401 basegfx::B3DPoint aVec(rVec);
402 aVec *= GetInvOrientation();
403 return aVec;
406 // B3dViewport -----------------------------------------------------------------
408 B3dViewport::B3dViewport()
409 : B3dTransformationSet(),
410 aVRP(0, 0, 0),
411 aVPN(0, 0, 1),
412 aVUV(0, 1, 0)
414 CalcOrientation();
417 B3dViewport::~B3dViewport()
421 void B3dViewport::SetVUV(const basegfx::B3DVector& rNewVUV)
423 aVUV = rNewVUV;
424 CalcOrientation();
427 void B3dViewport::SetViewportValues(
428 const basegfx::B3DPoint& rNewVRP,
429 const basegfx::B3DVector& rNewVPN,
430 const basegfx::B3DVector& rNewVUV)
432 aVRP = rNewVRP;
433 aVPN = rNewVPN;
434 aVUV = rNewVUV;
435 CalcOrientation();
438 void B3dViewport::CalcOrientation()
440 SetOrientation(aVRP, aVPN, aVUV);
443 // B3dCamera -------------------------------------------------------------------
445 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 bUseFocalLength(bUseFocLen)
456 CalcNewViewportValues();
459 B3dCamera::~B3dCamera()
463 void B3dCamera::DeviceRectangleChange()
465 // call parent
466 B3dViewport::DeviceRectangleChange();
468 // react to changes
469 CalcNewViewportValues();
472 void B3dCamera::CalcNewViewportValues()
474 basegfx::B3DVector aViewVector(aPosition - aLookAt);
475 basegfx::B3DVector aNewVPN(aViewVector);
477 basegfx::B3DVector aNewVUV(0.0, 1.0, 0.0);
478 if(aNewVPN.getLength() < aNewVPN.getY())
479 aNewVUV.setX(0.5);
481 aNewVUV.normalize();
482 aNewVPN.normalize();
484 basegfx::B3DVector aNewToTheRight = aNewVPN;
485 aNewToTheRight = aNewToTheRight.getPerpendicular(aNewVUV);
486 aNewToTheRight.normalize();
487 aNewVUV = aNewToTheRight.getPerpendicular(aNewVPN);
488 aNewVUV.normalize();
490 SetViewportValues(aPosition, aNewVPN, aNewVUV);
491 if(CalcFocalLength())
492 SetViewportValues(aCorrectedPosition, aNewVPN, aNewVUV);
494 if(fBankAngle != 0.0)
496 basegfx::B3DHomMatrix aRotMat;
497 aRotMat.rotate(0.0, 0.0, fBankAngle);
498 basegfx::B3DVector aUp(0.0, 1.0, 0.0);
499 aUp *= aRotMat;
500 aUp = EyeToWorldCoor(aUp);
501 aUp.normalize();
502 SetVUV(aUp);
506 bool B3dCamera::CalcFocalLength()
508 double fWidth = GetDeviceRectangleWidth();
509 bool bRetval = false;
511 if(bUseFocalLength)
513 // Update position if focal length changes
514 aCorrectedPosition = basegfx::B3DPoint(0.0, 0.0, fFocalLength * fWidth / 35.0);
515 aCorrectedPosition = EyeToWorldCoor(aCorrectedPosition);
516 bRetval = true;
518 else
520 // Adjust focal length based on given position
521 basegfx::B3DPoint aOldPosition;
522 aOldPosition = WorldToEyeCoor(aOldPosition);
523 if(fWidth != 0.0)
524 fFocalLength = aOldPosition.getZ() / fWidth * 35.0;
525 if(fFocalLength < 5.0)
526 fFocalLength = 5.0;
528 return bRetval;
531 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */