xref: /trunk/main/svx/source/engine3d/camera3d.cxx (revision f6e50924)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <svx/camera3d.hxx>
27 #include <tools/stream.hxx>
28 
29 /*************************************************************************
30 |*
31 |* Konstruktor
32 |*
33 \************************************************************************/
34 
Camera3D(const basegfx::B3DPoint & rPos,const basegfx::B3DPoint & rLookAt,double fFocalLen,double fBankAng)35 Camera3D::Camera3D(const basegfx::B3DPoint& rPos, const basegfx::B3DPoint& rLookAt,
36 				   double fFocalLen, double fBankAng) :
37 	aResetPos(rPos),
38 	aResetLookAt(rLookAt),
39 	fResetFocalLength(fFocalLen),
40 	fResetBankAngle(fBankAng),
41 	fBankAngle(fBankAng),
42 	bAutoAdjustProjection(sal_True)
43 {
44 	SetVPD(0);
45 	SetPosition(rPos);
46 	SetLookAt(rLookAt);
47 	SetFocalLength(fFocalLen);
48 }
49 
50 /*************************************************************************
51 |*
52 |* Default-Konstruktor
53 |*
54 \************************************************************************/
55 
Camera3D()56 Camera3D::Camera3D()
57 {
58 	basegfx::B3DPoint aVector3D(0.0 ,0.0 ,1.0);
59 	Camera3D(aVector3D, basegfx::B3DPoint());
60 }
61 
62 /*************************************************************************
63 |*
64 |* Konstruktor
65 |*
66 \************************************************************************/
67 
Reset()68 void Camera3D::Reset()
69 {
70 	SetVPD(0);
71 	fBankAngle = fResetBankAngle;
72 	SetPosition(aResetPos);
73 	SetLookAt(aResetLookAt);
74 	SetFocalLength(fResetFocalLength);
75 }
76 
77 /*************************************************************************
78 |*
79 |* Defaultwerte fuer Reset setzen
80 |*
81 \************************************************************************/
82 
SetDefaults(const basegfx::B3DPoint & rPos,const basegfx::B3DPoint & rLookAt,double fFocalLen,double fBankAng)83 void Camera3D::SetDefaults(const basegfx::B3DPoint& rPos, const basegfx::B3DPoint& rLookAt,
84 							double fFocalLen, double fBankAng)
85 {
86 	aResetPos			= rPos;
87 	aResetLookAt		= rLookAt;
88 	fResetFocalLength	= fFocalLen;
89 	fResetBankAngle 	= fBankAng;
90 }
91 
92 /*************************************************************************
93 |*
94 |* ViewWindow setzen und PRP anpassen
95 |*
96 \************************************************************************/
97 
SetViewWindow(double fX,double fY,double fW,double fH)98 void Camera3D::SetViewWindow(double fX, double fY, double fW, double fH)
99 {
100 	Viewport3D::SetViewWindow(fX, fY, fW, fH);
101 	if ( bAutoAdjustProjection )
102 		SetFocalLength(fFocalLength);
103 }
104 
105 /*************************************************************************
106 |*
107 |* Kameraposition setzen
108 |*
109 \************************************************************************/
110 
SetPosition(const basegfx::B3DPoint & rNewPos)111 void Camera3D::SetPosition(const basegfx::B3DPoint& rNewPos)
112 {
113 	if ( rNewPos != aPosition )
114 	{
115 		aPosition = rNewPos;
116 		SetVRP(aPosition);
117 		SetVPN(aPosition - aLookAt);
118 		SetBankAngle(fBankAngle);
119 	}
120 }
121 
122 /*************************************************************************
123 |*
124 |* Blickpunkt setzen
125 |*
126 \************************************************************************/
127 
SetLookAt(const basegfx::B3DPoint & rNewLookAt)128 void Camera3D::SetLookAt(const basegfx::B3DPoint& rNewLookAt)
129 {
130 	if ( rNewLookAt != aLookAt )
131 	{
132 		aLookAt = rNewLookAt;
133 		SetVPN(aPosition - aLookAt);
134 		SetBankAngle(fBankAngle);
135 	}
136 }
137 
138 /*************************************************************************
139 |*
140 |* Position und Blickpunkt setzen
141 |*
142 \************************************************************************/
143 
SetPosAndLookAt(const basegfx::B3DPoint & rNewPos,const basegfx::B3DPoint & rNewLookAt)144 void Camera3D::SetPosAndLookAt(const basegfx::B3DPoint& rNewPos,
145 							   const basegfx::B3DPoint& rNewLookAt)
146 {
147 	if ( rNewPos != aPosition || rNewLookAt != aLookAt )
148 	{
149 		aPosition = rNewPos;
150 		aLookAt = rNewLookAt;
151 
152 		SetVRP(aPosition);
153 		SetVPN(aPosition - aLookAt);
154 		SetBankAngle(fBankAngle);
155 	}
156 }
157 
158 /*************************************************************************
159 |*
160 |* seitlichen Neigungswinkel setzen
161 |*
162 \************************************************************************/
163 
SetBankAngle(double fAngle)164 void Camera3D::SetBankAngle(double fAngle)
165 {
166 	basegfx::B3DVector aDiff(aPosition - aLookAt);
167 	basegfx::B3DVector aPrj(aDiff);
168 	fBankAngle = fAngle;
169 
170 	if ( aDiff.getY() == 0 )
171 	{
172 		aPrj.setY(-1.0);
173 	}
174 	else
175 	{	// aPrj = Projektion von aDiff auf die XZ-Ebene
176 		aPrj.setY(0.0);
177 
178 		if ( aDiff.getY() < 0.0 )
179 		{
180 			aPrj = -aPrj;
181 		}
182 	}
183 
184 	// von aDiff nach oben zeigenden View-Up-Vektor berechnen
185 	aPrj = aPrj.getPerpendicular(aDiff);
186 	aPrj = aPrj.getPerpendicular(aDiff);
187 	aDiff.normalize();
188 
189 	// auf Z-Achse rotieren, dort um BankAngle drehen und zurueck
190 	basegfx::B3DHomMatrix aTf;
191 	const double fV(sqrt(aDiff.getY() * aDiff.getY() + aDiff.getZ() * aDiff.getZ()));
192 
193 	if ( fV != 0.0 )
194 	{
195 		basegfx::B3DHomMatrix aTemp;
196 		const double fSin(aDiff.getY() / fV);
197 		const double fCos(aDiff.getZ() / fV);
198 
199 		aTemp.set(1, 1, fCos);
200 		aTemp.set(2, 2, fCos);
201 		aTemp.set(2, 1, fSin);
202 		aTemp.set(1, 2, -fSin);
203 
204 		aTf *= aTemp;
205 	}
206 
207 	{
208 		basegfx::B3DHomMatrix aTemp;
209 		const double fSin(-aDiff.getX());
210 		const double fCos(fV);
211 
212 		aTemp.set(0, 0, fCos);
213 		aTemp.set(2, 2, fCos);
214 		aTemp.set(0, 2, fSin);
215 		aTemp.set(2, 0, -fSin);
216 
217 		aTf *= aTemp;
218 	}
219 
220 	aTf.rotate(0.0, 0.0, fBankAngle);
221 
222 	{
223 		basegfx::B3DHomMatrix aTemp;
224 		const double fSin(aDiff.getX());
225 		const double fCos(fV);
226 
227 		aTemp.set(0, 0, fCos);
228 		aTemp.set(2, 2, fCos);
229 		aTemp.set(0, 2, fSin);
230 		aTemp.set(2, 0, -fSin);
231 
232 		aTf *= aTemp;
233 	}
234 
235 	if ( fV != 0.0 )
236 	{
237 		basegfx::B3DHomMatrix aTemp;
238 		const double fSin(-aDiff.getY() / fV);
239 		const double fCos(aDiff.getZ() / fV);
240 
241 		aTemp.set(1, 1, fCos);
242 		aTemp.set(2, 2, fCos);
243 		aTemp.set(2, 1, fSin);
244 		aTemp.set(1, 2, -fSin);
245 
246 		aTf *= aTemp;
247 	}
248 
249 	SetVUV(aTf * aPrj);
250 }
251 
252 /*************************************************************************
253 |*
254 |* Brennweite setzen
255 |*
256 \************************************************************************/
257 
SetFocalLength(double fLen)258 void Camera3D::SetFocalLength(double fLen)
259 {
260 	if ( fLen < 5 )
261 		fLen = 5;
262 	SetPRP(basegfx::B3DPoint(0.0, 0.0, fLen / 35.0 * aViewWin.W));
263 	fFocalLength = fLen;
264 }
265 
266 /*************************************************************************
267 |*
268 |* Um die Kameraposition drehen, LookAt wird dabei veraendert
269 |*
270 \************************************************************************/
271 
Rotate(double fHAngle,double fVAngle)272 void Camera3D::Rotate(double fHAngle, double fVAngle)
273 {
274 	basegfx::B3DHomMatrix aTf;
275 	basegfx::B3DVector aDiff(aLookAt - aPosition);
276 	const double fV(sqrt(aDiff.getX() * aDiff.getX() + aDiff.getZ() * aDiff.getZ()));
277 
278 	if ( fV != 0.0 )
279 	{
280 		basegfx::B3DHomMatrix aTemp;
281 		const double fSin(aDiff.getZ() / fV);
282 		const double fCos(aDiff.getX() / fV);
283 
284 		aTemp.set(0, 0, fCos);
285 		aTemp.set(2, 2, fCos);
286 		aTemp.set(0, 2, fSin);
287 		aTemp.set(2, 0, -fSin);
288 
289 		aTf *= aTemp;
290 	}
291 
292 	{
293 		aTf.rotate(0.0, 0.0, fVAngle);
294 	}
295 
296 	if ( fV != 0.0 )
297 	{
298 		basegfx::B3DHomMatrix aTemp;
299 		const double fSin(-aDiff.getZ() / fV);
300 		const double fCos(aDiff.getX() / fV);
301 
302 		aTemp.set(0, 0, fCos);
303 		aTemp.set(2, 2, fCos);
304 		aTemp.set(0, 2, fSin);
305 		aTemp.set(2, 0, -fSin);
306 
307 		aTf *= aTemp;
308 	}
309 
310 	{
311 		aTf.rotate(0.0, fHAngle, 0.0);
312 	}
313 
314 	aDiff *= aTf;
315 	SetLookAt(aPosition + aDiff);
316 }
317 
318 
319 /*************************************************************************
320 |*
321 |* Um den Blickpunkt drehen, Position wird dabei veraendert
322 |*
323 \************************************************************************/
324 
RotateAroundLookAt(double fHAngle,double fVAngle)325 void Camera3D::RotateAroundLookAt(double fHAngle, double fVAngle)
326 {
327 	basegfx::B3DHomMatrix aTf;
328 	basegfx::B3DVector aDiff(aPosition - aLookAt);
329 	const double fV(sqrt(aDiff.getX() * aDiff.getX() + aDiff.getZ() * aDiff.getZ()));
330 
331 	if ( fV != 0.0 )
332 	{
333 		basegfx::B3DHomMatrix aTemp;
334 		const double fSin(aDiff.getZ() / fV);
335 		const double fCos(aDiff.getX() / fV);
336 
337 		aTemp.set(0, 0, fCos);
338 		aTemp.set(2, 2, fCos);
339 		aTemp.set(0, 2, fSin);
340 		aTemp.set(2, 0, -fSin);
341 
342 		aTf *= aTemp;
343 	}
344 
345 	{
346 		aTf.rotate(0.0, 0.0, fVAngle);
347 	}
348 
349 	if ( fV != 0.0 )
350 	{
351 		basegfx::B3DHomMatrix aTemp;
352 		const double fSin(-aDiff.getZ() / fV);
353 		const double fCos(aDiff.getX() / fV);
354 
355 		aTemp.set(0, 0, fCos);
356 		aTemp.set(2, 2, fCos);
357 		aTemp.set(0, 2, fSin);
358 		aTemp.set(2, 0, -fSin);
359 
360 		aTf *= aTemp;
361 	}
362 
363 	{
364 		aTf.rotate(0.0, fHAngle, 0.0);
365 	}
366 
367 	aDiff *= aTf;
368 	SetPosition(aLookAt + aDiff);
369 }
370 
371 /*************************************************************************
372 |*
373 |* FG: ??? Setzt wohl die Projektionsebene in eine bestimmte Tiefe
374 |*
375 \************************************************************************/
376 
SetFocalLengthWithCorrect(double fLen)377 void Camera3D::SetFocalLengthWithCorrect(double fLen)
378 {
379 	if ( fLen < 5.0 )
380 	{
381 		fLen = 5.0;
382 	}
383 
384 	SetPRP(basegfx::B3DPoint(0.0, 0.0, aPRP.getZ() * fLen / fFocalLength));
385 	fFocalLength = fLen;
386 }
387 
388 // eof
389