LibreOffice Module tools (master) 1
b3dtrans.cxx
Go to the documentation of this file.
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 // Near and far clipping planes
25constexpr double gfNearBound = 0.001;
26constexpr double gfFarBound = 1.001;
27
28
29// B3dTransformationSet --------------------------------------------------------
30// Transformations for all 3D output
31
33{
34 Reset();
35}
36
38{
39}
40
42{
43 rTarget.translate( -aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
44 aVUP.normalize();
45 aVPN.normalize();
46 basegfx::B3DVector aRx(aVUP);
47 basegfx::B3DVector aRy(aVPN);
48 aRx = aRx.getPerpendicular(aRy);
49 aRx.normalize();
50 aRy = aRy.getPerpendicular(aRx);
51 aRy.normalize();
53 aTemp.set(0, 0, aRx.getX());
54 aTemp.set(0, 1, aRx.getY());
55 aTemp.set(0, 2, aRx.getZ());
56 aTemp.set(1, 0, aRy.getX());
57 aTemp.set(1, 1, aRy.getY());
58 aTemp.set(1, 2, aRy.getZ());
59 aTemp.set(2, 0, aVPN.getX());
60 aTemp.set(2, 1, aVPN.getY());
61 aTemp.set(2, 2, aVPN.getZ());
62 rTarget *= aTemp;
63}
64
65void B3dTransformationSet::Frustum(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
66{
67 if(!(fNear > 0.0))
68 {
69 fNear = 0.001;
70 }
71 if(!(fFar > 0.0))
72 {
73 fFar = 1.0;
74 }
75 if(fNear == fFar)
76 {
77 fFar = fNear + 1.0;
78 }
79 if(fLeft == fRight)
80 {
81 fLeft -= 1.0;
82 fRight += 1.0;
83 }
84 if(fTop == fBottom)
85 {
86 fBottom -= 1.0;
87 fTop += 1.0;
88 }
90
91 aTemp.set(0, 0, 2.0 * fNear / (fRight - fLeft));
92 aTemp.set(1, 1, 2.0 * fNear / (fTop - fBottom));
93 aTemp.set(0, 2, (fRight + fLeft) / (fRight - fLeft));
94 aTemp.set(1, 2, (fTop + fBottom) / (fTop - fBottom));
95 aTemp.set(2, 2, -1.0 * ((fFar + fNear) / (fFar - fNear)));
96 aTemp.set(3, 2, -1.0);
97 aTemp.set(2, 3, -1.0 * ((2.0 * fFar * fNear) / (fFar - fNear)));
98 aTemp.set(3, 3, 0.0);
99
100 rTarget *= aTemp;
101}
102
104 double fLeft, double fRight, double fBottom, double fTop,
105 double fNear, double fFar)
106{
107 if(fNear == fFar)
108 {
109 OSL_FAIL("Near and far clipping plane in Ortho definition are identical");
110 fFar = fNear + 1.0;
111 }
112 if(fLeft == fRight)
113 {
114 OSL_FAIL("Left and right in Ortho definition are identical");
115 fLeft -= 1.0;
116 fRight += 1.0;
117 }
118 if(fTop == fBottom)
119 {
120 OSL_FAIL("Top and bottom in Ortho definition are identical");
121 fBottom -= 1.0;
122 fTop += 1.0;
123 }
125
126 aTemp.set(0, 0, 2.0 / (fRight - fLeft));
127 aTemp.set(1, 1, 2.0 / (fTop - fBottom));
128 aTemp.set(2, 2, -1.0 * (2.0 / (fFar - fNear)));
129 aTemp.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft)));
130 aTemp.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom)));
131 aTemp.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear)));
132
133 rTarget *= aTemp;
134}
135
138{
139 // Reset matrices to identity matrices
142
145
147
148 mfLeftBound = mfBottomBound = -1.0;
149 mfRightBound = mfTopBound = 1.0;
150
151 mfRatio = 0.0;
152
155
156 mbPerspective = true;
157
158 mbProjectionValid = false;
159
160 CalcViewport();
161}
162
165{
166 // Assign and compute inverse
169}
170
172{
174 Orientation(maOrientation, rVRP, rVPN, rVUP);
175
177}
178
180{
181 // Assign and compute inverse
184}
185
188{
189 maProjection = mProject;
191}
192
194{
196 CalcViewport();
197 return maProjection;
198}
199
201{
202 // Assign and compute inverse
205}
206
209{
210 // Parameters for projection
211 double fLeft(mfLeftBound);
212 double fRight(mfRightBound);
213 double fBottom(mfBottomBound);
214 double fTop(mfTopBound);
215
216 // Adjust projection to aspect ratio, if set
217 if(GetRatio() != 0.0)
218 {
219 // Compute current aspect ratio of boundaries
220 double fBoundWidth = static_cast<double>(maViewportRectangle.GetWidth() + 1);
221 double fBoundHeight = static_cast<double>(maViewportRectangle.GetHeight() + 1);
222 double fActRatio = 1;
223 double fFactor;
224
225 if(fBoundWidth != 0.0)
226 fActRatio = fBoundHeight / fBoundWidth;
227 // FIXME else in this case has a lot of problems, should this return.
228
229 // scale down larger part
230 if(fActRatio > mfRatio)
231 {
232 // scale down Y
233 fFactor = fActRatio;
234 fTop *= fFactor;
235 fBottom *= fFactor;
236 }
237 else
238 {
239 // scale down X
240 fFactor = 1.0 / fActRatio;
241 fRight *= fFactor;
242 fLeft *= fFactor;
243 }
244 }
245
246 // Do projection and object areas overlap?
248
249 // Reset projection with new values
250 basegfx::B3DHomMatrix aNewProjection;
251
252 // #i36281#
253 // OpenGL needs a little more rough additional size to not let
254 // the front face vanish. Changed from SMALL_DVALUE to 0.000001,
255 // which is 1/10000th, compared with 1/tenth of a million from SMALL_DVALUE.
256 const double fDistPart((gfFarBound - gfNearBound) * 0.0001);
257
258 // To avoid critical clipping, set Near & Far generously
259 if(mbPerspective)
260 {
261 Frustum(aNewProjection, fLeft, fRight, fBottom, fTop, gfNearBound - fDistPart, gfFarBound + fDistPart);
262 }
263 else
264 {
265 Ortho(aNewProjection, fLeft, fRight, fBottom, fTop, gfNearBound - fDistPart, gfFarBound + fDistPart);
266 }
267
268 // Set to true to guarantee loop termination
269 mbProjectionValid = true;
270
271 // set new projection
272 SetProjection(aNewProjection);
273
274 // fill parameters for ViewportTransformation
275 // Translation
276 maTranslate.setX(static_cast<double>(maSetBound.Left()) + ((maSetBound.GetWidth() - 1) / 2.0));
277 maTranslate.setY(static_cast<double>(maSetBound.Top()) + ((maSetBound.GetHeight() - 1) / 2.0));
279
280 // Scaling
281 maScale.setX((maSetBound.GetWidth() - 1) / 2.0);
282 maScale.setY((maSetBound.GetHeight() - 1) / -2.0);
284}
285
287{
288 if(mfRatio != fNew)
289 {
290 mfRatio = fNew;
291 mbProjectionValid = false;
292 }
293}
294
295void B3dTransformationSet::SetDeviceRectangle(double fL, double fR, double fB, double fT)
296{
297 if(fL != mfLeftBound || fR != mfRightBound || fB != mfBottomBound || fT != mfTopBound)
298 {
299 mfLeftBound = fL;
300 mfRightBound = fR;
301 mfBottomBound = fB;
302 mfTopBound = fT;
303
304 mbProjectionValid = false;
305
306 // Broadcast changes
308 }
309}
310
312{
313}
314
316{
317 if(mbPerspective != bNew)
318 {
319 mbPerspective = bNew;
320 mbProjectionValid = false;
321 }
322}
323
325{
326 if(rRect != maViewportRectangle || rVisible != maVisibleRectangle)
327 {
328 maViewportRectangle = rRect;
329 maVisibleRectangle = rVisible;
330
331 mbProjectionValid = false;
332 }
333}
334
335// direct access to various transformations
336
338{
339 basegfx::B3DPoint aVec(rVec);
340 aVec *= maOrientation;
341 return aVec;
342}
343
345{
346 basegfx::B3DPoint aVec(rVec);
347 aVec *= maInvOrientation;
348 return aVec;
349}
350
351// B3dViewport -----------------------------------------------------------------
352
354: aVRP(0, 0, 0),
355 aVPN(0, 0, 1),
356 aVUV(0, 1, 0)
357{
359}
360
362{
363}
364
366{
367 aVUV = rNewVUV;
369}
370
372 const basegfx::B3DPoint& rNewVRP,
373 const basegfx::B3DVector& rNewVPN,
374 const basegfx::B3DVector& rNewVUV)
375{
376 aVRP = rNewVRP;
377 aVPN = rNewVPN;
378 aVUV = rNewVUV;
380}
381
383{
385}
386
387// B3dCamera -------------------------------------------------------------------
388
390 const basegfx::B3DPoint& rPos, const basegfx::B3DVector& rLkAt,
391 double fFocLen, double fBnkAng)
392: aPosition(rPos),
393 aLookAt(rLkAt),
394 fFocalLength(fFocLen),
395 fBankAngle(fBnkAng)
396{
398}
399
401{
402}
403
405{
406 // call parent
408
409 // react to changes
411}
412
414{
416
417 basegfx::B3DVector aNewVUV(0.0, 1.0, 0.0);
418 if(aNewVPN.getLength() < aNewVPN.getY())
419 aNewVUV.setX(0.5);
420
421 aNewVUV.normalize();
422 aNewVPN.normalize();
423
424 basegfx::B3DVector aNewToTheRight = aNewVPN.getPerpendicular(aNewVUV);
425 aNewToTheRight.normalize();
426 aNewVUV = aNewToTheRight.getPerpendicular(aNewVPN);
427 aNewVUV.normalize();
428
429 SetViewportValues(aPosition, aNewVPN, aNewVUV);
431
432 if(fBankAngle != 0.0)
433 {
434 basegfx::B3DHomMatrix aRotMat;
435 aRotMat.rotate(0.0, 0.0, fBankAngle);
436 basegfx::B3DVector aUp(0.0, 1.0, 0.0);
437 aUp *= aRotMat;
438 aUp = EyeToWorldCoor(aUp);
439 aUp.normalize();
440 SetVUV(aUp);
441 }
442}
443
445{
446 double fWidth = GetDeviceRectangleWidth();
447
448 // Adjust focal length based on given position
449 basegfx::B3DPoint aOldPosition = WorldToEyeCoor({});
450 if(fWidth != 0.0)
451 fFocalLength = aOldPosition.getZ() / fWidth * 35.0;
452 if(fFocalLength < 5.0)
453 fFocalLength = 5.0;
454}
455
456/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr double gfNearBound
Definition: b3dtrans.cxx:25
constexpr double gfFarBound
Definition: b3dtrans.cxx:26
#define ZBUFFER_DEPTH_RANGE
Definition: b3dtrans.hxx:23
basegfx::B3DPoint aPosition
Definition: b3dtrans.hxx:208
void CalcNewViewportValues()
Definition: b3dtrans.cxx:413
B3dCamera(const basegfx::B3DPoint &rPos=basegfx::B3DPoint(0.0, 0.0, 1.0), const basegfx::B3DVector &rLkAt=basegfx::B3DVector(0.0, 0.0, 0.0), double fFocLen=35.0, double fBnkAng=0.0)
Definition: b3dtrans.cxx:389
double fBankAngle
Definition: b3dtrans.hxx:211
virtual void DeviceRectangleChange() override
Definition: b3dtrans.cxx:404
void CalcFocalLength()
Definition: b3dtrans.cxx:444
virtual ~B3dCamera() override
Definition: b3dtrans.cxx:400
double fFocalLength
Definition: b3dtrans.hxx:210
basegfx::B3DVector aLookAt
Definition: b3dtrans.hxx:209
basegfx::B3DPoint EyeToWorldCoor(const basegfx::B3DPoint &rVec)
Definition: b3dtrans.cxx:344
basegfx::B3DHomMatrix maInvProjection
Definition: b3dtrans.hxx:46
void SetDeviceRectangle(double fL=-1.0, double fR=1.0, double fB=-1.0, double fT=1.0)
Definition: b3dtrans.cxx:295
static void Orientation(basegfx::B3DHomMatrix &rTarget, const basegfx::B3DPoint &aVRP=basegfx::B3DPoint(0.0, 0.0, 1.0), basegfx::B3DVector aVPN=basegfx::B3DVector(0.0, 0.0, 1.0), basegfx::B3DVector aVUP=basegfx::B3DVector(0.0, 1.0, 0.0))
Definition: b3dtrans.cxx:41
void SetViewportRectangle(tools::Rectangle const &rRect, tools::Rectangle const &rVisible)
Definition: b3dtrans.cxx:324
basegfx::B3DHomMatrix maObjectTrans
Definition: b3dtrans.hxx:37
tools::Rectangle maVisibleRectangle
Definition: b3dtrans.hxx:69
basegfx::B3DVector maTranslate
Definition: b3dtrans.hxx:53
void PostSetObjectTrans()
Object transformation.
Definition: b3dtrans.cxx:164
const basegfx::B3DHomMatrix & GetProjection()
Definition: b3dtrans.cxx:193
tools::Rectangle maSetBound
Definition: b3dtrans.hxx:73
double GetDeviceRectangleWidth() const
Definition: b3dtrans.hxx:114
static void Ortho(basegfx::B3DHomMatrix &rTarget, double fLeft=-1.0, double fRight=1.0, double fBottom=-1.0, double fTop=1.0, double fNear=0.0, double fFar=1.0)
Definition: b3dtrans.cxx:103
virtual ~B3dTransformationSet()
Definition: b3dtrans.cxx:37
void SetRatio(double fNew)
Definition: b3dtrans.cxx:286
void SetOrientation(const basegfx::B3DPoint &rVRP=basegfx::B3DPoint(0.0, 0.0, 1.0), const basegfx::B3DVector &rVPN=basegfx::B3DVector(0.0, 0.0, 1.0), const basegfx::B3DVector &rVUP=basegfx::B3DVector(0.0, 1.0, 0.0))
Set the orientation.
Definition: b3dtrans.cxx:171
basegfx::B3DHomMatrix maProjection
Definition: b3dtrans.hxx:45
basegfx::B3DPoint WorldToEyeCoor(const basegfx::B3DPoint &rVec)
Definition: b3dtrans.cxx:337
basegfx::B3DVector maScale
Definition: b3dtrans.hxx:52
void Reset()
reset values
Definition: b3dtrans.cxx:137
basegfx::B3DHomMatrix maOrientation
Definition: b3dtrans.hxx:41
void SetPerspective(bool bNew)
Definition: b3dtrans.cxx:315
basegfx::B2DHomMatrix maTexture
Definition: b3dtrans.hxx:49
virtual void DeviceRectangleChange()
Definition: b3dtrans.cxx:311
static void Frustum(basegfx::B3DHomMatrix &rTarget, double fLeft=-1.0, double fRight=1.0, double fBottom=-1.0, double fTop=1.0, double fNear=0.001, double fFar=1.0)
Definition: b3dtrans.cxx:65
double GetRatio() const
Definition: b3dtrans.hxx:108
basegfx::B3DHomMatrix maInvOrientation
Definition: b3dtrans.hxx:42
basegfx::B3DHomMatrix maInvObjectTrans
Definition: b3dtrans.hxx:38
void SetProjection(const basegfx::B3DHomMatrix &mProject)
Projections for transformations.
Definition: b3dtrans.cxx:187
void CalcViewport()
Transformations for viewport.
Definition: b3dtrans.cxx:208
tools::Rectangle maViewportRectangle
Definition: b3dtrans.hxx:67
void SetVUV(const basegfx::B3DVector &rNewVUV)
Definition: b3dtrans.cxx:365
basegfx::B3DVector aVUV
Definition: b3dtrans.hxx:161
void SetViewportValues(const basegfx::B3DPoint &rNewVRP, const basegfx::B3DVector &rNewVPN, const basegfx::B3DVector &rNewVUV)
Definition: b3dtrans.cxx:371
basegfx::B3DPoint aVRP
Definition: b3dtrans.hxx:159
virtual ~B3dViewport() override
Definition: b3dtrans.cxx:361
basegfx::B3DVector aVPN
Definition: b3dtrans.hxx:160
void CalcOrientation()
Definition: b3dtrans.cxx:382
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
void rotate(double fAngleX, double fAngleY, double fAngleZ)
double getLength() const
B3DVector getPerpendicular(const B3DVector &rNormalizedVec) const
B3DVector & normalize()
void setX(TYPE fX)
TYPE getX() const
TYPE getZ() const
TYPE getY() const
void setY(TYPE fY)
void setZ(TYPE fZ)
constexpr tools::Long GetWidth() const
Returns the difference between right and left, assuming the range is inclusive.
Definition: gen.hxx:694
constexpr tools::Long Top() const
Definition: gen.hxx:502
constexpr tools::Long GetHeight() const
Returns the difference between bottom and top, assuming the range is inclusive.
Definition: gen.hxx:710
constexpr tools::Long Left() const
Definition: gen.hxx:500
FilterGroup & rTarget