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_drawinglayer.hxx" 26 27 #include <drawinglayer/geometry/viewinformation3d.hxx> 28 #include <basegfx/range/b3drange.hxx> 29 #include <basegfx/matrix/b3dhommatrix.hxx> 30 #include <com/sun/star/geometry/AffineMatrix3D.hpp> 31 #include <com/sun/star/geometry/RealRectangle3D.hpp> 32 #include <basegfx/tools/canvastools.hxx> 33 34 ////////////////////////////////////////////////////////////////////////////// 35 36 using namespace com::sun::star; 37 38 ////////////////////////////////////////////////////////////////////////////// 39 40 namespace drawinglayer 41 { 42 namespace geometry 43 { 44 /** Implementation class for ViewInformation3D 45 */ 46 class ImpViewInformation3D 47 { 48 private: 49 // ViewInformation3D implementation can change refcount, so we have only 50 // two memory regions for pairs of ViewInformation3D/ImpViewInformation3D 51 friend class ::drawinglayer::geometry::ViewInformation3D; 52 53 // the refcounter. 0 means exclusively used 54 sal_uInt32 mnRefCount; 55 56 // the 3D transformations 57 // Object to World. This may change and being adapted when entering 3D transformation 58 // groups 59 basegfx::B3DHomMatrix maObjectTransformation; 60 61 // World to Camera. This includes VRP, VPN and VUV camera coordinate system 62 basegfx::B3DHomMatrix maOrientation; 63 64 // Camera to Device with X,Y and Z [-1.0 .. 1.0]. This is the 65 // 3D to 2D projection which may be parallel or perspective. When it is perspective, 66 // the last line of the homogen matrix will NOT be unused 67 basegfx::B3DHomMatrix maProjection; 68 69 // Device to View with X,Y and Z [0.0 .. 1.0]. This converts from -1 to 1 coordinates 70 // in camera coordinate system to 0 to 1 in unit 2D coordinates. This way it stays 71 // view-independent. To get discrete coordinates, the 2D transformation of a scene 72 // as 2D object needs to be involved 73 basegfx::B3DHomMatrix maDeviceToView; 74 75 // Object to View is the linear combination of all four transformations. It's 76 // buffered to avoid too much matrix multiplying and created on demand 77 basegfx::B3DHomMatrix maObjectToView; 78 79 // the point in time 80 double mfViewTime; 81 82 // the complete PropertyValue representation (if already created) 83 uno::Sequence< beans::PropertyValue > mxViewInformation; 84 85 // the extra PropertyValues; does not contain the transformations 86 uno::Sequence< beans::PropertyValue > mxExtendedInformation; 87 88 // the local UNO API strings getNamePropertyObjectTransformation()89 const ::rtl::OUString& getNamePropertyObjectTransformation() 90 { 91 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation")); 92 return s_sNameProperty; 93 } 94 getNamePropertyOrientation()95 const ::rtl::OUString& getNamePropertyOrientation() 96 { 97 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Orientation")); 98 return s_sNameProperty; 99 } 100 getNamePropertyProjection()101 const ::rtl::OUString& getNamePropertyProjection() 102 { 103 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection")); 104 return s_sNameProperty; 105 } 106 getNamePropertyProjection_30()107 const ::rtl::OUString& getNamePropertyProjection_30() 108 { 109 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection30")); 110 return s_sNameProperty; 111 } 112 getNamePropertyProjection_31()113 const ::rtl::OUString& getNamePropertyProjection_31() 114 { 115 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection31")); 116 return s_sNameProperty; 117 } 118 getNamePropertyProjection_32()119 const ::rtl::OUString& getNamePropertyProjection_32() 120 { 121 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection32")); 122 return s_sNameProperty; 123 } 124 getNamePropertyProjection_33()125 const ::rtl::OUString& getNamePropertyProjection_33() 126 { 127 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Projection33")); 128 return s_sNameProperty; 129 } 130 getNamePropertyDeviceToView()131 const ::rtl::OUString& getNamePropertyDeviceToView() 132 { 133 static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("DeviceToView")); 134 return s_sNameProperty; 135 } 136 getNamePropertyTime()137 const ::rtl::OUString& getNamePropertyTime() 138 { 139 static ::rtl::OUString s_sNamePropertyTime(RTL_CONSTASCII_USTRINGPARAM("Time")); 140 return s_sNamePropertyTime; 141 } 142 143 // a central PropertyValue parsing method to allow transportation of 144 // all ViewParameters using UNO API impInterpretPropertyValues(const uno::Sequence<beans::PropertyValue> & rViewParameters)145 void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters) 146 { 147 if(rViewParameters.hasElements()) 148 { 149 const sal_Int32 nCount(rViewParameters.getLength()); 150 sal_Int32 nExtendedInsert(0); 151 152 // prepare extended information for filtering. Maximum size is nCount 153 mxExtendedInformation.realloc(nCount); 154 155 for(sal_Int32 a(0); a < nCount; a++) 156 { 157 const beans::PropertyValue& rProp = rViewParameters[a]; 158 159 if(rProp.Name == getNamePropertyObjectTransformation()) 160 { 161 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 162 rProp.Value >>= aAffineMatrix3D; 163 maObjectTransformation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 164 } 165 else if(rProp.Name == getNamePropertyOrientation()) 166 { 167 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 168 rProp.Value >>= aAffineMatrix3D; 169 maOrientation = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 170 } 171 else if(rProp.Name == getNamePropertyProjection()) 172 { 173 // projection may be defined using a frustum in which case the last line of 174 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, 175 // these four values need to be treated extra 176 const double f_30(maProjection.get(3, 0)); 177 const double f_31(maProjection.get(3, 1)); 178 const double f_32(maProjection.get(3, 2)); 179 const double f_33(maProjection.get(3, 3)); 180 181 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 182 rProp.Value >>= aAffineMatrix3D; 183 maProjection = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 184 185 maProjection.set(3, 0, f_30); 186 maProjection.set(3, 1, f_31); 187 maProjection.set(3, 2, f_32); 188 maProjection.set(3, 3, f_33); 189 } 190 else if(rProp.Name == getNamePropertyProjection_30()) 191 { 192 double f_30(0.0); 193 rProp.Value >>= f_30; 194 maProjection.set(3, 0, f_30); 195 } 196 else if(rProp.Name == getNamePropertyProjection_31()) 197 { 198 double f_31(0.0); 199 rProp.Value >>= f_31; 200 maProjection.set(3, 1, f_31); 201 } 202 else if(rProp.Name == getNamePropertyProjection_32()) 203 { 204 double f_32(0.0); 205 rProp.Value >>= f_32; 206 maProjection.set(3, 2, f_32); 207 } 208 else if(rProp.Name == getNamePropertyProjection_33()) 209 { 210 double f_33(1.0); 211 rProp.Value >>= f_33; 212 maProjection.set(3, 3, f_33); 213 } 214 else if(rProp.Name == getNamePropertyDeviceToView()) 215 { 216 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 217 rProp.Value >>= aAffineMatrix3D; 218 maDeviceToView = basegfx::unotools::homMatrixFromAffineMatrix3D(aAffineMatrix3D); 219 } 220 else if(rProp.Name == getNamePropertyTime()) 221 { 222 rProp.Value >>= mfViewTime; 223 } 224 else 225 { 226 // extra information; add to filtered information 227 mxExtendedInformation[nExtendedInsert++] = rProp; 228 } 229 } 230 231 // extra information size is now known; realloc to final size 232 mxExtendedInformation.realloc(nExtendedInsert); 233 } 234 } 235 236 // central method to create a Sequence of PropertyValues containing the complete 237 // data set impFillViewInformationFromContent()238 void impFillViewInformationFromContent() 239 { 240 uno::Sequence< beans::PropertyValue > xRetval; 241 const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity()); 242 const bool bOrientationUsed(!maOrientation.isIdentity()); 243 const bool bProjectionUsed(!maProjection.isIdentity()); 244 const bool bDeviceToViewUsed(!maDeviceToView.isIdentity()); 245 const bool bTimeUsed(0.0 < mfViewTime); 246 const bool bExtraInformation(mxExtendedInformation.hasElements()); 247 248 // projection may be defined using a frustum in which case the last line of 249 // the 4x4 matrix is not (0,0,0,1). Since AffineMatrix3D does not support that, 250 // these four values need to be treated extra 251 const bool bProjectionUsed_30(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 0))); 252 const bool bProjectionUsed_31(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 1))); 253 const bool bProjectionUsed_32(bProjectionUsed && !basegfx::fTools::equalZero(maProjection.get(3, 2))); 254 const bool bProjectionUsed_33(bProjectionUsed && !basegfx::fTools::equal(maProjection.get(3, 3), 1.0)); 255 256 sal_uInt32 nIndex(0); 257 const sal_uInt32 nCount( 258 (bObjectTransformationUsed ? 1 : 0) + 259 (bOrientationUsed ? 1 : 0) + 260 (bProjectionUsed ? 1 : 0) + 261 (bProjectionUsed_30 ? 1 : 0) + 262 (bProjectionUsed_31 ? 1 : 0) + 263 (bProjectionUsed_32 ? 1 : 0) + 264 (bProjectionUsed_33 ? 1 : 0) + 265 (bDeviceToViewUsed ? 1 : 0) + 266 (bTimeUsed ? 1 : 0) + 267 (bExtraInformation ? mxExtendedInformation.getLength() : 0)); 268 269 mxViewInformation.realloc(nCount); 270 271 if(bObjectTransformationUsed) 272 { 273 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 274 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maObjectTransformation); 275 mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation(); 276 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 277 nIndex++; 278 } 279 280 if(bOrientationUsed) 281 { 282 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 283 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maOrientation); 284 mxViewInformation[nIndex].Name = getNamePropertyOrientation(); 285 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 286 nIndex++; 287 } 288 289 if(bProjectionUsed) 290 { 291 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 292 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maProjection); 293 mxViewInformation[nIndex].Name = getNamePropertyProjection(); 294 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 295 nIndex++; 296 } 297 298 if(bProjectionUsed_30) 299 { 300 mxViewInformation[nIndex].Name = getNamePropertyProjection_30(); 301 mxViewInformation[nIndex].Value <<= maProjection.get(3, 0); 302 nIndex++; 303 } 304 305 if(bProjectionUsed_31) 306 { 307 mxViewInformation[nIndex].Name = getNamePropertyProjection_31(); 308 mxViewInformation[nIndex].Value <<= maProjection.get(3, 1); 309 nIndex++; 310 } 311 312 if(bProjectionUsed_32) 313 { 314 mxViewInformation[nIndex].Name = getNamePropertyProjection_32(); 315 mxViewInformation[nIndex].Value <<= maProjection.get(3, 2); 316 nIndex++; 317 } 318 319 if(bProjectionUsed_33) 320 { 321 mxViewInformation[nIndex].Name = getNamePropertyProjection_33(); 322 mxViewInformation[nIndex].Value <<= maProjection.get(3, 3); 323 nIndex++; 324 } 325 326 if(bDeviceToViewUsed) 327 { 328 com::sun::star::geometry::AffineMatrix3D aAffineMatrix3D; 329 basegfx::unotools::affineMatrixFromHomMatrix3D(aAffineMatrix3D, maDeviceToView); 330 mxViewInformation[nIndex].Name = getNamePropertyDeviceToView(); 331 mxViewInformation[nIndex].Value <<= aAffineMatrix3D; 332 nIndex++; 333 } 334 335 if(bTimeUsed) 336 { 337 mxViewInformation[nIndex].Name = getNamePropertyTime(); 338 mxViewInformation[nIndex].Value <<= mfViewTime; 339 nIndex++; 340 } 341 342 if(bExtraInformation) 343 { 344 const sal_Int32 nExtra(mxExtendedInformation.getLength()); 345 346 for(sal_Int32 a(0); a < nExtra; a++) 347 { 348 mxViewInformation[nIndex++] = mxExtendedInformation[a]; 349 } 350 } 351 } 352 353 public: ImpViewInformation3D(const basegfx::B3DHomMatrix & rObjectTransformation,const basegfx::B3DHomMatrix & rOrientation,const basegfx::B3DHomMatrix & rProjection,const basegfx::B3DHomMatrix & rDeviceToView,double fViewTime,const uno::Sequence<beans::PropertyValue> & rExtendedParameters)354 ImpViewInformation3D( 355 const basegfx::B3DHomMatrix& rObjectTransformation, 356 const basegfx::B3DHomMatrix& rOrientation, 357 const basegfx::B3DHomMatrix& rProjection, 358 const basegfx::B3DHomMatrix& rDeviceToView, 359 double fViewTime, 360 const uno::Sequence< beans::PropertyValue >& rExtendedParameters) 361 : mnRefCount(0), 362 maObjectTransformation(rObjectTransformation), 363 maOrientation(rOrientation), 364 maProjection(rProjection), 365 maDeviceToView(rDeviceToView), 366 mfViewTime(fViewTime), 367 mxViewInformation(), 368 mxExtendedInformation() 369 { 370 impInterpretPropertyValues(rExtendedParameters); 371 } 372 ImpViewInformation3D(const uno::Sequence<beans::PropertyValue> & rViewParameters)373 ImpViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) 374 : mnRefCount(0), 375 maObjectTransformation(), 376 maOrientation(), 377 maProjection(), 378 maDeviceToView(), 379 mfViewTime(), 380 mxViewInformation(rViewParameters), 381 mxExtendedInformation() 382 { 383 impInterpretPropertyValues(rViewParameters); 384 } 385 ImpViewInformation3D()386 ImpViewInformation3D() 387 : mnRefCount(0), 388 maObjectTransformation(), 389 maOrientation(), 390 maProjection(), 391 maDeviceToView(), 392 mfViewTime(), 393 mxViewInformation(), 394 mxExtendedInformation() 395 { 396 } 397 getObjectTransformation() const398 const basegfx::B3DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } getOrientation() const399 const basegfx::B3DHomMatrix& getOrientation() const { return maOrientation; } getProjection() const400 const basegfx::B3DHomMatrix& getProjection() const { return maProjection; } getDeviceToView() const401 const basegfx::B3DHomMatrix& getDeviceToView() const { return maDeviceToView; } getViewTime() const402 double getViewTime() const { return mfViewTime; } 403 getObjectToView() const404 const basegfx::B3DHomMatrix& getObjectToView() const 405 { 406 // on demand WorldToView creation 407 ::osl::Mutex m_mutex; 408 409 if(maObjectToView.isIdentity()) 410 { 411 const_cast< ImpViewInformation3D* >(this)->maObjectToView = maDeviceToView * maProjection * maOrientation * maObjectTransformation; 412 } 413 414 return maObjectToView; 415 } 416 getViewInformationSequence() const417 const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const 418 { 419 ::osl::Mutex m_mutex; 420 421 if(!mxViewInformation.hasElements()) 422 { 423 const_cast< ImpViewInformation3D* >(this)->impFillViewInformationFromContent(); 424 } 425 426 return mxViewInformation; 427 } 428 getExtendedInformationSequence() const429 const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const 430 { 431 return mxExtendedInformation; 432 } 433 operator ==(const ImpViewInformation3D & rCandidate) const434 bool operator==(const ImpViewInformation3D& rCandidate) const 435 { 436 return (maObjectTransformation == rCandidate.maObjectTransformation 437 && maOrientation == rCandidate.maOrientation 438 && maProjection == rCandidate.maProjection 439 && maDeviceToView == rCandidate.maDeviceToView 440 && mfViewTime == rCandidate.mfViewTime 441 && mxExtendedInformation == rCandidate.mxExtendedInformation); 442 } 443 get_global_default()444 static ImpViewInformation3D* get_global_default() 445 { 446 static ImpViewInformation3D* pDefault = 0; 447 448 if(!pDefault) 449 { 450 pDefault = new ImpViewInformation3D(); 451 452 // never delete; start with RefCount 1, not 0 453 pDefault->mnRefCount++; 454 } 455 456 return pDefault; 457 } 458 }; 459 } // end of anonymous namespace 460 } // end of namespace drawinglayer 461 462 ////////////////////////////////////////////////////////////////////////////// 463 464 namespace drawinglayer 465 { 466 namespace geometry 467 { ViewInformation3D(const basegfx::B3DHomMatrix & rObjectObjectTransformation,const basegfx::B3DHomMatrix & rOrientation,const basegfx::B3DHomMatrix & rProjection,const basegfx::B3DHomMatrix & rDeviceToView,double fViewTime,const uno::Sequence<beans::PropertyValue> & rExtendedParameters)468 ViewInformation3D::ViewInformation3D( 469 const basegfx::B3DHomMatrix& rObjectObjectTransformation, 470 const basegfx::B3DHomMatrix& rOrientation, 471 const basegfx::B3DHomMatrix& rProjection, 472 const basegfx::B3DHomMatrix& rDeviceToView, 473 double fViewTime, 474 const uno::Sequence< beans::PropertyValue >& rExtendedParameters) 475 : mpViewInformation3D(new ImpViewInformation3D( 476 rObjectObjectTransformation, rOrientation, rProjection, 477 rDeviceToView, fViewTime, rExtendedParameters)) 478 { 479 } 480 ViewInformation3D(const uno::Sequence<beans::PropertyValue> & rViewParameters)481 ViewInformation3D::ViewInformation3D(const uno::Sequence< beans::PropertyValue >& rViewParameters) 482 : mpViewInformation3D(new ImpViewInformation3D(rViewParameters)) 483 { 484 } 485 ViewInformation3D()486 ViewInformation3D::ViewInformation3D() 487 : mpViewInformation3D(ImpViewInformation3D::get_global_default()) 488 { 489 mpViewInformation3D->mnRefCount++; 490 } 491 ViewInformation3D(const ViewInformation3D & rCandidate)492 ViewInformation3D::ViewInformation3D(const ViewInformation3D& rCandidate) 493 : mpViewInformation3D(rCandidate.mpViewInformation3D) 494 { 495 ::osl::Mutex m_mutex; 496 mpViewInformation3D->mnRefCount++; 497 } 498 ~ViewInformation3D()499 ViewInformation3D::~ViewInformation3D() 500 { 501 ::osl::Mutex m_mutex; 502 503 if(mpViewInformation3D->mnRefCount) 504 { 505 mpViewInformation3D->mnRefCount--; 506 } 507 else 508 { 509 delete mpViewInformation3D; 510 } 511 } 512 isDefault() const513 bool ViewInformation3D::isDefault() const 514 { 515 return mpViewInformation3D == ImpViewInformation3D::get_global_default(); 516 } 517 operator =(const ViewInformation3D & rCandidate)518 ViewInformation3D& ViewInformation3D::operator=(const ViewInformation3D& rCandidate) 519 { 520 ::osl::Mutex m_mutex; 521 522 if(mpViewInformation3D->mnRefCount) 523 { 524 mpViewInformation3D->mnRefCount--; 525 } 526 else 527 { 528 delete mpViewInformation3D; 529 } 530 531 mpViewInformation3D = rCandidate.mpViewInformation3D; 532 mpViewInformation3D->mnRefCount++; 533 534 return *this; 535 } 536 operator ==(const ViewInformation3D & rCandidate) const537 bool ViewInformation3D::operator==(const ViewInformation3D& rCandidate) const 538 { 539 if(rCandidate.mpViewInformation3D == mpViewInformation3D) 540 { 541 return true; 542 } 543 544 if(rCandidate.isDefault() != isDefault()) 545 { 546 return false; 547 } 548 549 return (*rCandidate.mpViewInformation3D == *mpViewInformation3D); 550 } 551 getObjectTransformation() const552 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectTransformation() const 553 { 554 return mpViewInformation3D->getObjectTransformation(); 555 } 556 getOrientation() const557 const basegfx::B3DHomMatrix& ViewInformation3D::getOrientation() const 558 { 559 return mpViewInformation3D->getOrientation(); 560 } 561 getProjection() const562 const basegfx::B3DHomMatrix& ViewInformation3D::getProjection() const 563 { 564 return mpViewInformation3D->getProjection(); 565 } 566 getDeviceToView() const567 const basegfx::B3DHomMatrix& ViewInformation3D::getDeviceToView() const 568 { 569 return mpViewInformation3D->getDeviceToView(); 570 } 571 getObjectToView() const572 const basegfx::B3DHomMatrix& ViewInformation3D::getObjectToView() const 573 { 574 return mpViewInformation3D->getObjectToView(); 575 } 576 getViewTime() const577 double ViewInformation3D::getViewTime() const 578 { 579 return mpViewInformation3D->getViewTime(); 580 } 581 getViewInformationSequence() const582 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getViewInformationSequence() const 583 { 584 return mpViewInformation3D->getViewInformationSequence(); 585 } 586 getExtendedInformationSequence() const587 const uno::Sequence< beans::PropertyValue >& ViewInformation3D::getExtendedInformationSequence() const 588 { 589 return mpViewInformation3D->getExtendedInformationSequence(); 590 } 591 } // end of namespace geometry 592 } // end of namespace drawinglayer 593 594 ////////////////////////////////////////////////////////////////////////////// 595 // eof 596