xref: /trunk/main/tools/source/generic/b3dtrans.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_tools.hxx"
30 #include <tools/b3dtrans.hxx>
31 #include <tools/debug.hxx>
32 
33 /*************************************************************************
34 |*
35 |* Transformationen fuer alle 3D Ausgaben
36 |*
37 \************************************************************************/
38 
39 B3dTransformationSet::B3dTransformationSet()
40 {
41     Reset();
42 }
43 
44 B3dTransformationSet::~B3dTransformationSet()
45 {
46 }
47 
48 void B3dTransformationSet::Orientation(basegfx::B3DHomMatrix& rTarget, basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
49 {
50     rTarget.translate( -aVRP.getX(), -aVRP.getY(), -aVRP.getZ());
51     aVUP.normalize();
52     aVPN.normalize();
53     basegfx::B3DVector aRx(aVUP);
54     basegfx::B3DVector aRy(aVPN);
55     aRx = aRx.getPerpendicular(aRy);
56     aRx.normalize();
57     aRy = aRy.getPerpendicular(aRx);
58     aRy.normalize();
59     basegfx::B3DHomMatrix aTemp;
60     aTemp.set(0, 0, aRx.getX());
61     aTemp.set(0, 1, aRx.getY());
62     aTemp.set(0, 2, aRx.getZ());
63     aTemp.set(1, 0, aRy.getX());
64     aTemp.set(1, 1, aRy.getY());
65     aTemp.set(1, 2, aRy.getZ());
66     aTemp.set(2, 0, aVPN.getX());
67     aTemp.set(2, 1, aVPN.getY());
68     aTemp.set(2, 2, aVPN.getZ());
69     rTarget *= aTemp;
70 }
71 
72 void B3dTransformationSet::Frustum(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
73 {
74     if(!(fNear > 0.0))
75     {
76         fNear = 0.001;
77     }
78     if(!(fFar > 0.0))
79     {
80         fFar = 1.0;
81     }
82     if(fNear == fFar)
83     {
84         fFar = fNear + 1.0;
85     }
86     if(fLeft == fRight)
87     {
88         fLeft -= 1.0;
89         fRight += 1.0;
90     }
91     if(fTop == fBottom)
92     {
93         fBottom -= 1.0;
94         fTop += 1.0;
95     }
96     basegfx::B3DHomMatrix aTemp;
97 
98     aTemp.set(0, 0, 2.0 * fNear / (fRight - fLeft));
99     aTemp.set(1, 1, 2.0 * fNear / (fTop - fBottom));
100     aTemp.set(0, 2, (fRight + fLeft) / (fRight - fLeft));
101     aTemp.set(1, 2, (fTop + fBottom) / (fTop - fBottom));
102     aTemp.set(2, 2, -1.0 * ((fFar + fNear) / (fFar - fNear)));
103     aTemp.set(3, 2, -1.0);
104     aTemp.set(2, 3, -1.0 * ((2.0 * fFar * fNear) / (fFar - fNear)));
105     aTemp.set(3, 3, 0.0);
106 
107     rTarget *= aTemp;
108 }
109 
110 void B3dTransformationSet::Ortho(basegfx::B3DHomMatrix& rTarget, double fLeft, double fRight, double fBottom, double fTop, double fNear, double fFar)
111 {
112     if(fNear == fFar)
113     {
114         DBG_ERROR("Near and far clipping plane in Ortho definition are identical");
115         fFar = fNear + 1.0;
116     }
117     if(fLeft == fRight)
118     {
119         DBG_ERROR("Left and right in Ortho definition are identical");
120         fLeft -= 1.0;
121         fRight += 1.0;
122     }
123     if(fTop == fBottom)
124     {
125         DBG_ERROR("Top and bottom in Ortho definition are identical");
126         fBottom -= 1.0;
127         fTop += 1.0;
128     }
129     basegfx::B3DHomMatrix aTemp;
130 
131     aTemp.set(0, 0, 2.0 / (fRight - fLeft));
132     aTemp.set(1, 1, 2.0 / (fTop - fBottom));
133     aTemp.set(2, 2, -1.0 * (2.0 / (fFar - fNear)));
134     aTemp.set(0, 3, -1.0 * ((fRight + fLeft) / (fRight - fLeft)));
135     aTemp.set(1, 3, -1.0 * ((fTop + fBottom) / (fTop - fBottom)));
136     aTemp.set(2, 3, -1.0 * ((fFar + fNear) / (fFar - fNear)));
137 
138     rTarget *= aTemp;
139 }
140 
141 /*************************************************************************
142 |*
143 |* Reset der Werte
144 |*
145 \************************************************************************/
146 
147 void B3dTransformationSet::Reset()
148 {
149     // Matritzen auf Einheitsmatritzen
150     maObjectTrans.identity();
151     PostSetObjectTrans();
152 
153     Orientation(maOrientation);
154     PostSetOrientation();
155 
156     maTexture.identity();
157 
158     mfLeftBound = mfBottomBound = -1.0;
159     mfRightBound = mfTopBound = 1.0;
160     mfNearBound = 0.001;
161     mfFarBound = 1.001;
162 
163     meRatio = Base3DRatioGrow;
164     mfRatio = 0.0;
165 
166     maViewportRectangle = Rectangle(-1, -1, 2, 2);
167     maVisibleRectangle = maViewportRectangle;
168 
169     mbPerspective = sal_True;
170 
171     mbProjectionValid = sal_False;
172     mbObjectToDeviceValid = sal_False;
173     mbWorldToViewValid = sal_False;
174 
175     CalcViewport();
176 }
177 
178 /*************************************************************************
179 |*
180 |* Objekttransformation
181 |*
182 \************************************************************************/
183 
184 void B3dTransformationSet::SetObjectTrans(const basegfx::B3DHomMatrix& rObj)
185 {
186     maObjectTrans = rObj;
187 
188     mbObjectToDeviceValid = sal_False;
189     mbInvTransObjectToEyeValid = sal_False;
190 
191     PostSetObjectTrans();
192 }
193 
194 void B3dTransformationSet::PostSetObjectTrans()
195 {
196     // Zuweisen und Inverse bestimmen
197     maInvObjectTrans = maObjectTrans;
198     maInvObjectTrans.invert();
199 }
200 
201 /*************************************************************************
202 |*
203 |* Orientierungstransformation
204 |*
205 \************************************************************************/
206 
207 void B3dTransformationSet::SetOrientation( basegfx::B3DPoint aVRP, basegfx::B3DVector aVPN, basegfx::B3DVector aVUP)
208 {
209     maOrientation.identity();
210     Orientation(maOrientation, aVRP, aVPN, aVUP);
211 
212     mbInvTransObjectToEyeValid = sal_False;
213     mbObjectToDeviceValid = sal_False;
214     mbWorldToViewValid = sal_False;
215 
216     PostSetOrientation();
217 }
218 
219 void B3dTransformationSet::SetOrientation(basegfx::B3DHomMatrix& mOrient)
220 {
221     maOrientation = mOrient;
222 
223     mbInvTransObjectToEyeValid = sal_False;
224     mbObjectToDeviceValid = sal_False;
225     mbWorldToViewValid = sal_False;
226 
227     PostSetOrientation();
228 }
229 
230 void B3dTransformationSet::PostSetOrientation()
231 {
232     // Zuweisen und Inverse bestimmen
233     maInvOrientation = maOrientation;
234     maInvOrientation.invert();
235 }
236 
237 /*************************************************************************
238 |*
239 |* Projektionstransformation
240 |*
241 \************************************************************************/
242 
243 void B3dTransformationSet::SetProjection(const basegfx::B3DHomMatrix& mProject)
244 {
245     maProjection = mProject;
246     PostSetProjection();
247 }
248 
249 const basegfx::B3DHomMatrix& B3dTransformationSet::GetProjection()
250 {
251     if(!mbProjectionValid)
252         CalcViewport();
253     return maProjection;
254 }
255 
256 const basegfx::B3DHomMatrix& B3dTransformationSet::GetInvProjection()
257 {
258     if(!mbProjectionValid)
259         CalcViewport();
260     return maInvProjection;
261 }
262 
263 void B3dTransformationSet::PostSetProjection()
264 {
265     // Zuweisen und Inverse bestimmen
266     maInvProjection = GetProjection();
267     maInvProjection.invert();
268 
269     // Abhaengige Matritzen invalidieren
270     mbObjectToDeviceValid = sal_False;
271     mbWorldToViewValid = sal_False;
272 }
273 
274 /*************************************************************************
275 |*
276 |* Texturtransformation
277 |*
278 \************************************************************************/
279 
280 void B3dTransformationSet::SetTexture(const basegfx::B2DHomMatrix& rTxt)
281 {
282     maTexture = rTxt;
283     PostSetTexture();
284 }
285 
286 void B3dTransformationSet::PostSetTexture()
287 {
288 }
289 
290 /*************************************************************************
291 |*
292 |* Viewport-Transformation
293 |*
294 \************************************************************************/
295 
296 void B3dTransformationSet::CalcViewport()
297 {
298     // Faktoren fuer die Projektion
299     double fLeft(mfLeftBound);
300     double fRight(mfRightBound);
301     double fBottom(mfBottomBound);
302     double fTop(mfTopBound);
303 
304     // Soll das Seitenverhaeltnis Beachtung finden?
305     // Falls ja, Bereich der Projektion an Seitenverhaeltnis anpassen
306     if(GetRatio() != 0.0)
307     {
308         // Berechne aktuelles Seitenverhaeltnis der Bounds
309         double fBoundWidth = (double)(maViewportRectangle.GetWidth() + 1);
310         double fBoundHeight = (double)(maViewportRectangle.GetHeight() + 1);
311         double fActRatio = 1;
312         double fFactor;
313 
314         if(fBoundWidth != 0.0)
315             fActRatio = fBoundHeight / fBoundWidth;
316         // FIXME   else in this case has a lot of problems,  should this return.
317 
318         switch(meRatio)
319         {
320             case Base3DRatioShrink :
321             {
322                 // Kleineren Teil vergroessern
323                 if(fActRatio > mfRatio)
324                 {
325                     // X vergroessern
326                     fFactor = 1.0 / fActRatio;
327                     fRight  *= fFactor;
328                     fLeft *= fFactor;
329                 }
330                 else
331                 {
332                     // Y vergroessern
333                     fFactor = fActRatio;
334                     fTop *= fFactor;
335                     fBottom *= fFactor;
336                 }
337                 break;
338             }
339             case Base3DRatioGrow :
340             {
341                 // GroesserenTeil verkleinern
342                 if(fActRatio > mfRatio)
343                 {
344                     // Y verkleinern
345                     fFactor = fActRatio;
346                     fTop *= fFactor;
347                     fBottom *= fFactor;
348                 }
349                 else
350                 {
351                     // X verkleinern
352                     fFactor = 1.0 / fActRatio;
353                     fRight  *= fFactor;
354                     fLeft *= fFactor;
355                 }
356                 break;
357             }
358             case Base3DRatioMiddle :
359             {
360                 // Mitteln
361                 fFactor = ((1.0 / fActRatio) + 1.0) / 2.0;
362                 fRight *= fFactor;
363                 fLeft *= fFactor;
364                 fFactor = (fActRatio + 1.0) / 2.0;
365                 fTop *= fFactor;
366                 fBottom *= fFactor;
367                 break;
368             }
369         }
370     }
371 
372     // Ueberschneiden sich Darstellungsflaeche und Objektflaeche?
373     maSetBound = maViewportRectangle;
374 
375     // Mit den neuen Werten Projektion und ViewPort setzen
376     basegfx::B3DHomMatrix aNewProjection;
377 
378     // #i36281#
379     // OpenGL needs a little more rough additional size to not let
380     // the front face vanish. Changed from SMALL_DVALUE to 0.000001,
381     // which is 1/10000th, comared with 1/tenth of a million from SMALL_DVALUE.
382     const double fDistPart((mfFarBound - mfNearBound) * 0.0001);
383 
384     // Near, Far etwas grosszuegiger setzen, um falsches,
385     // zu kritisches clippen zu verhindern
386     if(mbPerspective)
387     {
388         Frustum(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
389     }
390     else
391     {
392         Ortho(aNewProjection, fLeft, fRight, fBottom, fTop, mfNearBound - fDistPart, mfFarBound + fDistPart);
393     }
394 
395     // jetzt schon auf gueltig setzen um Endlosschleife zu vermeiden
396     mbProjectionValid = sal_True;
397 
398     // Neue Projektion setzen
399     SetProjection(aNewProjection);
400 
401     // fill parameters for ViewportTransformation
402     // Translation
403     maTranslate.setX((double)maSetBound.Left() + ((maSetBound.GetWidth() - 1L) / 2.0));
404     maTranslate.setY((double)maSetBound.Top() + ((maSetBound.GetHeight() - 1L) / 2.0));
405     maTranslate.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
406 
407     // Skalierung
408     maScale.setX((maSetBound.GetWidth() - 1L) / 2.0);
409     maScale.setY((maSetBound.GetHeight() - 1L) / -2.0);
410     maScale.setZ(ZBUFFER_DEPTH_RANGE / 2.0);
411 
412     // Auf Veraenderung des ViewPorts reagieren
413     PostSetViewport();
414 }
415 
416 void B3dTransformationSet::SetRatio(double fNew)
417 {
418     if(mfRatio != fNew)
419     {
420         mfRatio = fNew;
421         mbProjectionValid = sal_False;
422         mbObjectToDeviceValid = sal_False;
423         mbWorldToViewValid = sal_False;
424     }
425 }
426 
427 void B3dTransformationSet::SetRatioMode(Base3DRatio eNew)
428 {
429     if(meRatio != eNew)
430     {
431         meRatio = eNew;
432         mbProjectionValid = sal_False;
433         mbObjectToDeviceValid = sal_False;
434         mbWorldToViewValid = sal_False;
435     }
436 }
437 
438 void B3dTransformationSet::SetDeviceRectangle(double fL, double fR, double fB, double fT,
439     sal_Bool bBroadCastChange)
440 {
441     if(fL != mfLeftBound || fR != mfRightBound || fB != mfBottomBound || fT != mfTopBound)
442     {
443         mfLeftBound = fL;
444         mfRightBound = fR;
445         mfBottomBound = fB;
446         mfTopBound = fT;
447 
448         mbProjectionValid = sal_False;
449         mbObjectToDeviceValid = sal_False;
450         mbWorldToViewValid = sal_False;
451 
452         // Aenderung bekanntmachen
453         if(bBroadCastChange)
454             DeviceRectangleChange();
455     }
456 }
457 
458 void B3dTransformationSet::SetDeviceVolume(const basegfx::B3DRange& rVol, sal_Bool bBroadCastChange)
459 {
460     SetDeviceRectangle(rVol.getMinX(), rVol.getMaxX(), rVol.getMinY(), rVol.getMaxY(), bBroadCastChange);
461     SetFrontClippingPlane(rVol.getMinZ());
462     SetBackClippingPlane(rVol.getMaxZ());
463 }
464 
465 void B3dTransformationSet::DeviceRectangleChange()
466 {
467 }
468 
469 void B3dTransformationSet::GetDeviceRectangle(double &fL, double &fR, double& fB, double& fT)
470 {
471     fL = mfLeftBound;
472     fR = mfRightBound;
473     fB = mfBottomBound;
474     fT = mfTopBound;
475 
476     mbProjectionValid = sal_False;
477     mbObjectToDeviceValid = sal_False;
478     mbWorldToViewValid = sal_False;
479 }
480 
481 basegfx::B3DRange B3dTransformationSet::GetDeviceVolume()
482 {
483     basegfx::B3DRange aRet;
484 
485     aRet.expand(basegfx::B3DTuple(mfLeftBound, mfBottomBound, mfNearBound));
486     aRet.expand(basegfx::B3DTuple(mfRightBound, mfTopBound, mfFarBound));
487 
488     return aRet;
489 }
490 
491 void B3dTransformationSet::SetFrontClippingPlane(double fF)
492 {
493     if(mfNearBound != fF)
494     {
495         mfNearBound = fF;
496         mbProjectionValid = sal_False;
497         mbObjectToDeviceValid = sal_False;
498         mbWorldToViewValid = sal_False;
499     }
500 }
501 
502 void B3dTransformationSet::SetBackClippingPlane(double fB)
503 {
504     if(mfFarBound != fB)
505     {
506         mfFarBound = fB;
507         mbProjectionValid = sal_False;
508         mbObjectToDeviceValid = sal_False;
509         mbWorldToViewValid = sal_False;
510     }
511 }
512 
513 void B3dTransformationSet::SetPerspective(sal_Bool bNew)
514 {
515     if(mbPerspective != bNew)
516     {
517         mbPerspective = bNew;
518         mbProjectionValid = sal_False;
519         mbObjectToDeviceValid = sal_False;
520         mbWorldToViewValid = sal_False;
521     }
522 }
523 
524 void B3dTransformationSet::SetViewportRectangle(Rectangle& rRect, Rectangle& rVisible)
525 {
526     if(rRect != maViewportRectangle || rVisible != maVisibleRectangle)
527     {
528         maViewportRectangle = rRect;
529         maVisibleRectangle = rVisible;
530 
531         mbProjectionValid = sal_False;
532         mbObjectToDeviceValid = sal_False;
533         mbWorldToViewValid = sal_False;
534     }
535 }
536 
537 void B3dTransformationSet::PostSetViewport()
538 {
539 }
540 
541 const Rectangle& B3dTransformationSet::GetLogicalViewportBounds()
542 {
543     if(!mbProjectionValid)
544         CalcViewport();
545     return maSetBound;
546 }
547 
548 const basegfx::B3DVector& B3dTransformationSet::GetScale()
549 {
550     if(!mbProjectionValid)
551         CalcViewport();
552     return maScale;
553 }
554 
555 const basegfx::B3DVector& B3dTransformationSet::GetTranslate()
556 {
557     if(!mbProjectionValid)
558         CalcViewport();
559     return maTranslate;
560 }
561 
562 /*************************************************************************
563 |*
564 |* Hilfsmatrixberechnungsroutinen
565 |*
566 \************************************************************************/
567 
568 void B3dTransformationSet::CalcMatObjectToDevice()
569 {
570     // ObjectToDevice berechnen (Orientation * Projection * Object)
571     maObjectToDevice = maObjectTrans;
572     maObjectToDevice *= maOrientation;
573     maObjectToDevice *= GetProjection();
574 
575     // auf gueltig setzen
576     mbObjectToDeviceValid = sal_True;
577 }
578 
579 const basegfx::B3DHomMatrix& B3dTransformationSet::GetObjectToDevice()
580 {
581     if(!mbObjectToDeviceValid)
582         CalcMatObjectToDevice();
583     return maObjectToDevice;
584 }
585 
586 void B3dTransformationSet::CalcMatInvTransObjectToEye()
587 {
588     maInvTransObjectToEye = maObjectTrans;
589     maInvTransObjectToEye *= maOrientation;
590     maInvTransObjectToEye.invert();
591     maInvTransObjectToEye.transpose();
592 
593     // eventuelle Translationen rausschmeissen, da diese
594     // Matrix nur zur Transformation von Vektoren gedacht ist
595     maInvTransObjectToEye.set(3, 0, 0.0);
596     maInvTransObjectToEye.set(3, 1, 0.0);
597     maInvTransObjectToEye.set(3, 2, 0.0);
598     maInvTransObjectToEye.set(3, 3, 1.0);
599 
600     // auf gueltig setzen
601     mbInvTransObjectToEyeValid = sal_True;
602 }
603 
604 const basegfx::B3DHomMatrix& B3dTransformationSet::GetInvTransObjectToEye()
605 {
606     if(!mbInvTransObjectToEyeValid)
607         CalcMatInvTransObjectToEye();
608     return maInvTransObjectToEye;
609 }
610 
611 basegfx::B3DHomMatrix B3dTransformationSet::GetMatFromObjectToView()
612 {
613     basegfx::B3DHomMatrix aFromObjectToView = GetObjectToDevice();
614 
615     const basegfx::B3DVector& rScale(GetScale());
616     aFromObjectToView.scale(rScale.getX(), rScale.getY(), rScale.getZ());
617     const basegfx::B3DVector& rTranslate(GetTranslate());
618     aFromObjectToView.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
619 
620     return aFromObjectToView;
621 }
622 
623 void B3dTransformationSet::CalcMatFromWorldToView()
624 {
625     maMatFromWorldToView = maOrientation;
626     maMatFromWorldToView *= GetProjection();
627     const basegfx::B3DVector& rScale(GetScale());
628     maMatFromWorldToView.scale(rScale.getX(), rScale.getY(), rScale.getZ());
629     const basegfx::B3DVector& rTranslate(GetTranslate());
630     maMatFromWorldToView.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
631     maInvMatFromWorldToView = maMatFromWorldToView;
632     maInvMatFromWorldToView.invert();
633 
634     // gueltig setzen
635     mbWorldToViewValid = sal_True;
636 }
637 
638 const basegfx::B3DHomMatrix& B3dTransformationSet::GetMatFromWorldToView()
639 {
640     if(!mbWorldToViewValid)
641         CalcMatFromWorldToView();
642     return maMatFromWorldToView;
643 }
644 
645 const basegfx::B3DHomMatrix& B3dTransformationSet::GetInvMatFromWorldToView()
646 {
647     if(!mbWorldToViewValid)
648         CalcMatFromWorldToView();
649     return maInvMatFromWorldToView;
650 }
651 
652 /*************************************************************************
653 |*
654 |* Direkter Zugriff auf verschiedene Transformationen
655 |*
656 \************************************************************************/
657 
658 const basegfx::B3DPoint B3dTransformationSet::WorldToEyeCoor(const basegfx::B3DPoint& rVec)
659 {
660     basegfx::B3DPoint aVec(rVec);
661     aVec *= GetOrientation();
662     return aVec;
663 }
664 
665 const basegfx::B3DPoint B3dTransformationSet::EyeToWorldCoor(const basegfx::B3DPoint& rVec)
666 {
667     basegfx::B3DPoint aVec(rVec);
668     aVec *= GetInvOrientation();
669     return aVec;
670 }
671 
672 const basegfx::B3DPoint B3dTransformationSet::EyeToViewCoor(const basegfx::B3DPoint& rVec)
673 {
674     basegfx::B3DPoint aVec(rVec);
675     aVec *= GetProjection();
676     aVec *= GetScale();
677     aVec += GetTranslate();
678     return aVec;
679 }
680 
681 const basegfx::B3DPoint B3dTransformationSet::ViewToEyeCoor(const basegfx::B3DPoint& rVec)
682 {
683     basegfx::B3DPoint aVec(rVec);
684     aVec -= GetTranslate();
685     aVec = aVec / GetScale();
686     aVec *= GetInvProjection();
687     return aVec;
688 }
689 
690 const basegfx::B3DPoint B3dTransformationSet::WorldToViewCoor(const basegfx::B3DPoint& rVec)
691 {
692     basegfx::B3DPoint aVec(rVec);
693     aVec *= GetMatFromWorldToView();
694     return aVec;
695 }
696 
697 const basegfx::B3DPoint B3dTransformationSet::ViewToWorldCoor(const basegfx::B3DPoint& rVec)
698 {
699     basegfx::B3DPoint aVec(rVec);
700     aVec *= GetInvMatFromWorldToView();
701     return aVec;
702 }
703 
704 const basegfx::B3DPoint B3dTransformationSet::DeviceToViewCoor(const basegfx::B3DPoint& rVec)
705 {
706     basegfx::B3DPoint aVec(rVec);
707     aVec *= GetScale();
708     aVec += GetTranslate();
709     return aVec;
710 }
711 
712 const basegfx::B3DPoint B3dTransformationSet::ViewToDeviceCoor(const basegfx::B3DPoint& rVec)
713 {
714     basegfx::B3DPoint aVec(rVec);
715     aVec -= GetTranslate();
716     aVec = aVec / GetScale();
717     return aVec;
718 }
719 
720 const basegfx::B3DPoint B3dTransformationSet::ObjectToWorldCoor(const basegfx::B3DPoint& rVec)
721 {
722     basegfx::B3DPoint aVec(rVec);
723     aVec *= GetObjectTrans();
724     return aVec;
725 }
726 
727 const basegfx::B3DPoint B3dTransformationSet::WorldToObjectCoor(const basegfx::B3DPoint& rVec)
728 {
729     basegfx::B3DPoint aVec(rVec);
730     aVec *= GetInvObjectTrans();
731     return aVec;
732 }
733 
734 const basegfx::B3DPoint B3dTransformationSet::ObjectToViewCoor(const basegfx::B3DPoint& rVec)
735 {
736     basegfx::B3DPoint aVec(rVec);
737     aVec *= GetObjectTrans();
738     aVec *= GetMatFromWorldToView();
739     return aVec;
740 }
741 
742 const basegfx::B3DPoint B3dTransformationSet::ViewToObjectCoor(const basegfx::B3DPoint& rVec)
743 {
744     basegfx::B3DPoint aVec(rVec);
745     aVec *= GetInvMatFromWorldToView();
746     aVec *= GetInvObjectTrans();
747     return aVec;
748 }
749 
750 const basegfx::B3DPoint B3dTransformationSet::ObjectToEyeCoor(const basegfx::B3DPoint& rVec)
751 {
752     basegfx::B3DPoint aVec(rVec);
753     aVec *= GetObjectTrans();
754     aVec *= GetOrientation();
755     return aVec;
756 }
757 
758 const basegfx::B3DPoint B3dTransformationSet::EyeToObjectCoor(const basegfx::B3DPoint& rVec)
759 {
760     basegfx::B3DPoint aVec(rVec);
761     aVec *= GetInvOrientation();
762     aVec *= GetInvObjectTrans();
763     return aVec;
764 }
765 
766 const basegfx::B3DPoint B3dTransformationSet::DeviceToEyeCoor(const basegfx::B3DPoint& rVec)
767 {
768     basegfx::B3DPoint aVec(rVec);
769     aVec *= GetInvProjection();
770     return aVec;
771 }
772 
773 const basegfx::B3DPoint B3dTransformationSet::EyeToDeviceCoor(const basegfx::B3DPoint& rVec)
774 {
775     basegfx::B3DPoint aVec(rVec);
776     aVec *= GetProjection();
777     return aVec;
778 }
779 
780 const basegfx::B3DPoint B3dTransformationSet::InvTransObjectToEye(const basegfx::B3DPoint& rVec)
781 {
782     basegfx::B3DPoint aVec(rVec);
783     aVec *= GetInvTransObjectToEye();
784     return aVec;
785 }
786 
787 const basegfx::B2DPoint B3dTransformationSet::TransTextureCoor(const basegfx::B2DPoint& rVec)
788 {
789     basegfx::B2DPoint aVec(rVec);
790     aVec *= GetTexture();
791     return aVec;
792 }
793 
794 /*************************************************************************
795 |*
796 |* Konstruktor B3dViewport
797 |*
798 \************************************************************************/
799 
800 B3dViewport::B3dViewport()
801 :   B3dTransformationSet(),
802     aVRP(0, 0, 0),
803     aVPN(0, 0, 1),
804     aVUV(0, 1, 0)
805 {
806     CalcOrientation();
807 }
808 
809 B3dViewport::~B3dViewport()
810 {
811 }
812 
813 void B3dViewport::SetVRP(const basegfx::B3DPoint& rNewVRP)
814 {
815     aVRP = rNewVRP;
816     CalcOrientation();
817 }
818 
819 void B3dViewport::SetVPN(const basegfx::B3DVector& rNewVPN)
820 {
821     aVPN = rNewVPN;
822     CalcOrientation();
823 }
824 
825 void B3dViewport::SetVUV(const basegfx::B3DVector& rNewVUV)
826 {
827     aVUV = rNewVUV;
828     CalcOrientation();
829 }
830 
831 void B3dViewport::SetViewportValues(
832     const basegfx::B3DPoint& rNewVRP,
833     const basegfx::B3DVector& rNewVPN,
834     const basegfx::B3DVector& rNewVUV)
835 {
836     aVRP = rNewVRP;
837     aVPN = rNewVPN;
838     aVUV = rNewVUV;
839     CalcOrientation();
840 }
841 
842 void B3dViewport::CalcOrientation()
843 {
844     SetOrientation(aVRP, aVPN, aVUV);
845 }
846 
847 /*************************************************************************
848 |*
849 |* Konstruktor B3dViewport
850 |*
851 \************************************************************************/
852 
853 B3dCamera::B3dCamera(
854     const basegfx::B3DPoint& rPos, const basegfx::B3DVector& rLkAt,
855     double fFocLen, double fBnkAng, sal_Bool bUseFocLen)
856 :   B3dViewport(),
857     aPosition(rPos),
858     aCorrectedPosition(rPos),
859     aLookAt(rLkAt),
860     fFocalLength(fFocLen),
861     fBankAngle(fBnkAng),
862     bUseFocalLength(bUseFocLen)
863 {
864     CalcNewViewportValues();
865 }
866 
867 B3dCamera::~B3dCamera()
868 {
869 }
870 
871 void B3dCamera::SetPosition(const basegfx::B3DPoint& rNewPos)
872 {
873     if(rNewPos != aPosition)
874     {
875         // Zuweisen
876         aCorrectedPosition = aPosition = rNewPos;
877 
878         // Neuberechnung
879         CalcNewViewportValues();
880     }
881 }
882 
883 void B3dCamera::SetLookAt(const basegfx::B3DVector& rNewLookAt)
884 {
885     if(rNewLookAt != aLookAt)
886     {
887         // Zuweisen
888         aLookAt = rNewLookAt;
889 
890         // Neuberechnung
891         CalcNewViewportValues();
892     }
893 }
894 
895 void B3dCamera::SetPositionAndLookAt(const basegfx::B3DPoint& rNewPos, const basegfx::B3DVector& rNewLookAt)
896 {
897     if(rNewPos != aPosition || rNewLookAt != aLookAt)
898     {
899         // Zuweisen
900         aPosition = rNewPos;
901         aLookAt = rNewLookAt;
902 
903         // Neuberechnung
904         CalcNewViewportValues();
905     }
906 }
907 
908 void B3dCamera::SetFocalLength(double fLen)
909 {
910     if(fLen != fFocalLength)
911     {
912         // Zuweisen
913         if(fLen < 5.0)
914             fLen = 5.0;
915         fFocalLength = fLen;
916 
917         // Neuberechnung
918         CalcNewViewportValues();
919     }
920 }
921 
922 void B3dCamera::SetBankAngle(double fAngle)
923 {
924     if(fAngle != fBankAngle)
925     {
926         // Zuweisen
927         fBankAngle = fAngle;
928 
929         // Neuberechnung
930         CalcNewViewportValues();
931     }
932 }
933 
934 void B3dCamera::SetUseFocalLength(sal_Bool bNew)
935 {
936     if(bNew != (sal_Bool)bUseFocalLength)
937     {
938         // Zuweisen
939         bUseFocalLength = bNew;
940 
941         // Neuberechnung
942         CalcNewViewportValues();
943     }
944 }
945 
946 void B3dCamera::DeviceRectangleChange()
947 {
948     // call parent
949     B3dViewport::DeviceRectangleChange();
950 
951     // Auf Aenderung reagieren
952     CalcNewViewportValues();
953 }
954 
955 void B3dCamera::CalcNewViewportValues()
956 {
957     basegfx::B3DVector aViewVector(aPosition - aLookAt);
958     basegfx::B3DVector aNewVPN(aViewVector);
959 
960     basegfx::B3DVector aNewVUV(0.0, 1.0, 0.0);
961     if(aNewVPN.getLength() < aNewVPN.getY())
962         aNewVUV.setX(0.5);
963 
964     aNewVUV.normalize();
965     aNewVPN.normalize();
966 
967     basegfx::B3DVector aNewToTheRight = aNewVPN;
968     aNewToTheRight = aNewToTheRight.getPerpendicular(aNewVUV);
969     aNewToTheRight.normalize();
970     aNewVUV = aNewToTheRight.getPerpendicular(aNewVPN);
971     aNewVUV.normalize();
972 
973     SetViewportValues(aPosition, aNewVPN, aNewVUV);
974     if(CalcFocalLength())
975         SetViewportValues(aCorrectedPosition, aNewVPN, aNewVUV);
976 
977     if(fBankAngle != 0.0)
978     {
979         basegfx::B3DHomMatrix aRotMat;
980         aRotMat.rotate(0.0, 0.0, fBankAngle);
981         basegfx::B3DVector aUp(0.0, 1.0, 0.0);
982         aUp *= aRotMat;
983         aUp = EyeToWorldCoor(aUp);
984         aUp.normalize();
985         SetVUV(aUp);
986     }
987 }
988 
989 sal_Bool B3dCamera::CalcFocalLength()
990 {
991     double fWidth = GetDeviceRectangleWidth();
992     sal_Bool bRetval = sal_False;
993 
994     if(bUseFocalLength)
995     {
996         // Position aufgrund der FocalLength korrigieren
997         aCorrectedPosition = basegfx::B3DPoint(0.0, 0.0, fFocalLength * fWidth / 35.0);
998         aCorrectedPosition = EyeToWorldCoor(aCorrectedPosition);
999         bRetval = sal_True;
1000     }
1001     else
1002     {
1003         // FocalLength anhand der Position anpassen
1004         basegfx::B3DPoint aOldPosition;
1005         aOldPosition = WorldToEyeCoor(aOldPosition);
1006         if(fWidth != 0.0)
1007             fFocalLength = aOldPosition.getZ() / fWidth * 35.0;
1008         if(fFocalLength < 5.0)
1009             fFocalLength = 5.0;
1010     }
1011     return bRetval;
1012 }
1013 
1014 // eof
1015