1 /* $NoKeywords: $ */ 2 /* 3 // 4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. 5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert 6 // McNeel & Associates. 7 // 8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF 10 // MERCHANTABILITY ARE HEREBY DISCLAIMED. 11 // 12 // For complete openNURBS copyright information see <http://www.opennurbs.org>. 13 // 14 //////////////////////////////////////////////////////////////// 15 */ 16 17 //////////////////////////////////////////////////////////////// 18 // 19 // defines ON_TextureMapping 20 // 21 //////////////////////////////////////////////////////////////// 22 23 #if !defined(OPENNURBS_TEXTURE_MAPPING_INC_) 24 #define OPENNURBS_TEXTURE_MAPPING_INC_ 25 26 /////////////////////////////////////////////////////////////////////////////// 27 // 28 // Class ON_TextureMapping 29 // 30 class ON_Line; 31 class ON_BrepFace; 32 class ON_3dPoint; 33 34 typedef int ( *TEXMAP_INTERSECT_LINE_SURFACE )( const ON_Line*, const ON_BrepFace*, ON_SimpleArray<ON_X_EVENT>& ); 35 typedef bool ( *TEXMAP_BREP_FACE_CLOSEST_POINT )( const ON_BrepFace*, const ON_3dPoint*, ON_3dPoint& ); 36 37 class ON_CLASS ON_TextureMapping : public ON_Object 38 { 39 public: 40 ON_OBJECT_DECLARE(ON_TextureMapping); 41 42 ON_TextureMapping(); 43 ~ON_TextureMapping(); 44 45 // The copy constructor and operator= overrides are needed 46 // to ensure m_geometry is properly copied. 47 ON_TextureMapping(const ON_TextureMapping& src); 48 ON_TextureMapping& operator=(const ON_TextureMapping& src); 49 50 // overrides virtual ON_Object::IsValid 51 ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const; 52 53 // overrides virtual ON_Object::Dump 54 void Dump( ON_TextLog& ) const; 55 56 // overrides virtual ON_Object::SizeOf 57 unsigned int SizeOf() const; 58 59 // overrides virtual ON_Object::Write 60 ON_BOOL32 Write( 61 ON_BinaryArchive& binary_archive 62 ) const; 63 64 // overrides virtual ON_Object::Read 65 ON_BOOL32 Read( 66 ON_BinaryArchive& binary_archive 67 ); 68 69 void Default(); 70 71 virtual 72 ON_UUID ModelObjectId() const; 73 74 /* 75 Determines whether the mapping, as currently set up, requires vertex normals to be present on the 76 mesh in order to evaluate the mapping correctly. 77 */ 78 bool RequiresVertexNormals() const; 79 bool IsPeriodic(void) const; 80 81 /* 82 Description: 83 Create a mapping that will convert surface parameters into 84 normalized (0,1)x(0,1) texture coordinates. 85 */ 86 bool SetSurfaceParameterMapping(void); 87 88 /* 89 Description: 90 Create a planar projection texture mapping. 91 Parameters: 92 plane - [in] 93 dx - [in] portion of the plane's x axis that is mapped to [0,1] 94 (can be a decreasing interval) 95 dy - [in] portion of the plane's x axis that is mapped to [0,1] 96 (can be a decreasing interval) 97 dz - [in] portion of the plane's x axis that is mapped to [0,1] 98 (can be a decreasing interval) 99 projection_method - [in] 100 1: Closest point mapping. 101 A target point P is mapped to the point on the plane 102 that is closest to P. The target normal is ignored. 103 2: Target line mapping. A target point-vector pair 104 (P, N), are mapped to the point on the plane 105 where the line through P, parallel to N, intersects 106 the plane. If the line is parallel to the plane, 107 the closest point mapping is used. 108 Example: 109 Create a mapping that maps the world axis aligned rectangle in 110 the world yz plane with corners at (0,3,5) and (0,7,19) to the 111 texture coordinate unit square. 112 113 ON_3dVector plane_xaxis(0.0,1.0,0.0); 114 ON_3dVector plane_yaxis(0.0,0,0,1.0); 115 ON_3dPoint plane_origin(0.0,2.0,4.0); 116 ON_Plane plane(plane_origin,plane_xaxis,plane_yaxis); 117 ON_Interval dx( 0.0, 7.0 - 3.0); 118 ON_Interval dy( 0.0, 19.0 - 5.0); 119 ON_Interval dz( 0.0, 1.0 ); 120 ON_TextureMapping mapping; 121 mapping.CreatePlaneMapping(plane,dx,dy,dz); 122 123 Returns: 124 True if input is valid. 125 */ 126 bool SetPlaneMapping( 127 const ON_Plane& plane, 128 const ON_Interval& dx, 129 const ON_Interval& dy, 130 const ON_Interval& dz 131 ); 132 133 /* 134 Description: 135 Create a cylindrical projection texture mapping. 136 Parameters: 137 cylinder - [in] 138 cylinder in world space used to define a cylindrical 139 coordinate system. The angular parameter maps (0,2pi) 140 to texture "u" (0,1), The height parameter maps 141 (height[0],height[1]) to texture "v" (0,1), and 142 the radial parameter maps (0,r) to texture "w" (0,1). 143 bIsCapped - [in] 144 If true, the cylinder is treated as a finite 145 capped cylinder. 146 Returns: 147 True if input is valid. 148 Remarks: 149 When the cylinder is capped and m_texture_space = divided, 150 the cylinder is mapped to texture space as follows: 151 The side is mapped to 0 <= "u" <= 2/3. 152 The bottom is mapped to 2/3 <= "u" <= 5/6. 153 The top is mapped to 5/6 <= "u" <= 5/6. 154 This is the same convention box mapping uses. 155 */ 156 bool SetCylinderMapping( 157 const ON_Cylinder& cylinder, 158 bool bIsCapped 159 ); 160 161 /* 162 Description: 163 Create a spherical projection texture mapping. 164 Parameters: 165 sphere - [in] 166 sphere in world space used to define a spherical 167 coordinate system. The longitude parameter maps 168 (0,2pi) to texture "u" (0,1). The latitude paramter 169 maps (-pi/2,+pi/2) to texture "v" (0,1). 170 The radial parameter maps (0,r) to texture "w" (0,1). 171 Returns: 172 True if input is valid. 173 */ 174 bool SetSphereMapping( 175 const ON_Sphere& sphere 176 ); 177 178 /* 179 Description: 180 Create a box projection texture mapping. 181 Parameters: 182 plane - [in] 183 The sides of the box the box are parallel to the 184 plane's coordinate planes. The dx, dy, dz intervals 185 determine the location of the sides. 186 dx - [in] 187 Determines the location of the front and back planes. 188 The vector plane.xaxis is perpendicular to these planes 189 and they pass through plane.PointAt(dx[0],0,0) and 190 plane.PointAt(dx[1],0,0), respectivly. 191 dy - [in] 192 Determines the location of the left and right planes. 193 The vector plane.yaxis is perpendicular to these planes 194 and they pass through plane.PointAt(0,dy[0],0) and 195 plane.PointAt(0,dy[1],0), respectivly. 196 dz - [in] 197 Determines the location of the top and bottom planes. 198 The vector plane.zaxis is perpendicular to these planes 199 and they pass through plane.PointAt(0,0,dz[0]) and 200 plane.PointAt(0,0,dz[1]), respectivly. 201 bIsCapped - [in] 202 If true, the box is treated as a finite 203 capped box. 204 Returns: 205 True if input is valid. 206 Remarks: 207 When m_texture_space = divided, the box is mapped to texture 208 space as follows: 209 210 If the box is not capped, then each side maps to 1/4 of the texture map. 211 212 v=1+---------+---------+---------+---------+ 213 | x=dx[1] | y=dy[1] | x=dx[0] | y=dy[0] | 214 | Front | Right | Back | Left | 215 | --y-> | <-x-- | <-y-- | --x-> | 216 v=0+---------+---------+---------+---------+ 217 0/4 <=u<= 1/4 <=u<= 2/4 <=u<= 3/4 <=u<= 4/4 218 219 If the box is capped, then each side and cap gets 1/6 of the texture map. 220 221 v=1+---------+---------+---------+---------+---------+---------+ 222 | x=dx[1] | y=dy[1] | x=dx[0] | y=dy[0] | z=dx[1] | z=dz[0] | 223 | Front | Right | Back | Left | Top | Bottom | 224 | --y-> | <-x-- | <-y-- | --x-> | --x-> | --x-> | 225 v=0+---------+---------+---------+---------+---------+---------+ 226 0/6 <=u<= 1/6 <=u<= 2/6 <=u<= 3/6 <=u<= 4/6 <=u<= 5/6 <=u<= 6/6 227 */ 228 bool SetBoxMapping( 229 const ON_Plane& plane, 230 ON_Interval dx, 231 ON_Interval dy, 232 ON_Interval dz, 233 bool bIsCapped 234 ); 235 236 /* 237 Description: 238 Get plane mapping parameters from this texture mapping. 239 Parameters: 240 plane - [out] 241 dx - [out] 242 Portion of the plane's x axis that is mapped to [0,1] 243 dy - [out] 244 Portion of the plane's y axis that is mapped to [0,1] 245 dz - [out] 246 Portion of the plane's z axis that is mapped to [0,1] 247 Returns: 248 True if valid plane mapping parameters were returned. 249 Remarks: 250 NOTE WELL: 251 Generally, GetMappingPlane will not return the same 252 parameters passed to SetPlaneMapping. However, the 253 location of the plane will be the same. 254 */ 255 bool GetMappingPlane( 256 ON_Plane& plane, 257 ON_Interval& dx, 258 ON_Interval& dy, 259 ON_Interval& dz 260 ) const; 261 262 /* 263 Description: 264 Get a cylindrical projection parameters from this texture mapping. 265 Parameters: 266 cylinder - [out] 267 Returns: 268 True if a valid cylinder is returned. 269 Remarks: 270 Generally, GetMappingCylinder will not return the same 271 parameters passed to SetCylinderMapping. However, the 272 location of the cylinder will be the same. 273 If this mapping is not cylindrical, the cylinder will 274 approximate the actual mapping primitive. 275 */ 276 bool GetMappingCylinder( 277 ON_Cylinder& cylinder 278 ) const; 279 280 /* 281 Description: 282 Get a spherical projection parameters from this texture mapping. 283 Parameters: 284 sphere - [out] 285 Returns: 286 True if a valid sphere is returned. 287 Remarks: 288 Generally, GetMappingShere will not return the same 289 parameters passed to SetSphereMapping. However, the 290 location of the sphere will be the same. 291 If this mapping is not cylindrical, the cylinder will 292 approximate the actual mapping primitive. 293 */ 294 bool GetMappingSphere( 295 ON_Sphere& sphere 296 ) const; 297 298 /* 299 Get a box projection from the texture mapping. 300 Parameters: 301 plane - [out] 302 The center of the box is at plane.origin and the sides 303 of the box are parallel to the plane's coordinate planes. 304 dx - [out] 305 The "front" and "back" sides of the box are in spanned 306 by the vectors plane.yaxis and plane.zaxis. The back 307 plane contains the point plane.PointAt(dx[0],0,0) and 308 the front plane contains the point plane.PointAt(dx[1],0,0). 309 dy - [out] 310 The "left" and "right" sides of the box are in spanned 311 by the vectors plane.zaxis and plane.xaxis. The left 312 plane contains the point plane.PointAt(0,dx[0],0) and 313 the back plane contains the point plane.PointAt(0,dy[1],0). 314 dz - [out] 315 The "top" and "bottom" sides of the box are in spanned 316 by the vectors plane.xaxis and plane.yaxis. The bottom 317 plane contains the point plane.PointAt(0,0,dz[0]) and 318 the top plane contains the point plane.PointAt(0,0,dz[1]). 319 Returns: 320 True if a valid box is returned. 321 Remarks: 322 Generally, GetMappingBox will not return the same 323 parameters passed to SetBoxMapping. However, the 324 location of the box will be the same. 325 */ 326 bool GetMappingBox( 327 ON_Plane& plane, 328 ON_Interval& dx, 329 ON_Interval& dy, 330 ON_Interval& dz 331 ) const; 332 333 334 /* 335 Description: 336 Reverses the texture in the specified direction. 337 Parameters: 338 dir - [in] 0 = reverse "u", 1 = reverse "v", 2 = reverse "w". 339 Remarks: 340 Modies m_uvw so that the spedified direction transforms 341 the texture coordinate t to 1-t. 342 Returns: 343 True if input is valid. 344 */ 345 bool ReverseTextureCoordinate( int dir ); 346 347 /* 348 Description: 349 Swaps the specified texture coordinates. 350 Parameters: 351 i - [in] 352 j - [in] 353 Remarks: 354 Modifies m_uvw so that the specified texture coordinates are swapped. 355 Returns: 356 True if input is valid. 357 */ 358 bool SwapTextureCoordinate( int i, int j ); 359 360 /* 361 Description: 362 Tiles the specified texture coordinates. 363 Parameters: 364 dir - [in] 0 = "u", 1 = "v", 2 = "w". 365 count - [in] number of tiles 366 offset - [in] offset of the tile 367 Remarks: 368 Modies m_uvw so that the specified texture coordinate is 369 tiled. 370 Returns: 371 True if input is valid. 372 */ 373 bool TileTextureCoordinate( int dir, double count, double offset ); 374 375 /* 376 Description: 377 Evaluate the mapping to get a texture coordinate. 378 Parameters: 379 P - [in] Vertex location 380 N - [in] If the mapping projection is ray_projection, 381 then this is the vertex unit normal. Otherwise 382 N is ignored. 383 T - [out] Texture coordinate (u,v,w) 384 385 P_xform -[in] 386 Transformation to be applied to P before performing 387 the mapping calculation. 388 N_xform - [in] 389 Transformation to be applied to N before performing 390 the mapping calculation. One way to calculate N_xform 391 is to use the call P_xform::GetVectorTransform(N_xform). 392 393 Returns: 394 Nonzero if evaluation is successful. When the mapping 395 is a box or capped cylinder mapping, the value indicates 396 which side was evaluated. 397 398 Cylinder mapping: 399 1 = cylinder wall, 2 = bottom cap, 3 = top cap 400 Box mapping: 401 1 = front 402 2 = right 403 3 = back 404 4 = left 405 5 = bottom 406 6 = top 407 408 See Also: 409 ON_TextureMapping::GetTextureCoordinates 410 ON_Mesh::SetTextureCoordinates 411 */ 412 virtual 413 int Evaluate( 414 const ON_3dPoint& P, 415 const ON_3dVector& N, 416 ON_3dPoint* T 417 ) const; 418 419 virtual 420 int Evaluate( 421 const ON_3dPoint& P, 422 const ON_3dVector& N, 423 ON_3dPoint* T, 424 const ON_Xform& P_xform, 425 const ON_Xform& N_xform 426 ) const; 427 428 int EvaluatePlaneMapping( 429 const ON_3dPoint& P, 430 const ON_3dVector& N, 431 ON_3dPoint* T 432 ) const; 433 434 int EvaluateSphereMapping( 435 const ON_3dPoint& P, 436 const ON_3dVector& N, 437 ON_3dPoint* T 438 ) const; 439 440 int EvaluateCylinderMapping( 441 const ON_3dPoint& P, 442 const ON_3dVector& N, 443 ON_3dPoint* T 444 ) const; 445 446 int EvaluateBoxMapping( 447 const ON_3dPoint& P, 448 const ON_3dVector& N, 449 ON_3dPoint* T 450 ) const; 451 452 /* 453 Description: 454 Quickly check to see if a mesh or tag has texture coordinates 455 set by this mapping. 456 Parameters: 457 mesh - [in] 458 tag - [in] 459 object_xform - [in] (optional) 460 If this transform is not NULL, then true will be 461 returned only if the mapping function is the same and 462 the tag's m_mesh_xform field is the same as mesh_xform. 463 This parameter is typically NULL or the value of 464 ON_MappingRef::m_object_xform. 465 Returns: 466 True if the meshes texture coordinates were set by this 467 mapping. 468 */ 469 bool HasMatchingTextureCoordinates( 470 const ON_Mesh& mesh, 471 const ON_Xform* object_xform = 0 472 ) const; 473 bool HasMatchingTextureCoordinates( 474 const class ON_MappingTag& tag, 475 const ON_Xform* object_xform = 0 476 ) const; 477 478 /* 479 Description: 480 Get texture coordinates. This calculation is 481 expensive. When possible, use a MappingMatch() 482 query to avoid unnecessary calculations. 483 Parameters: 484 mesh - [in] 485 T - [out] Texture coordinates returned here. 486 mesh_xform - [in] (optional) 487 If the mesh has been transformed since the texture mapping was set 488 up, pass the transformation here. Typically this is the value 489 of ON_Mesh::m_mapping_xform or ON_MappingRef::m_object_xform 490 bLazy - [in] 491 If true and the mesh.m_T[] values were calculated using 492 this mapping, they are simply copied to the T[] array 493 and no calculations are performed. If you are calling 494 the 3d point version and you care about the z-coordinate, 495 then do not use the lazy option (meshes only store 496 2d texture coordinates). 497 Tside - [out] 498 In the case of divided textures, side information is returned 499 here if a lazy mapping is not done. Otherwise Tside->Count() 500 will be zero. 501 Cylinder mapping: 502 1 = cylinder wall, 2 = bottom cap, 3 = top cap 503 Box mapping: 504 1 = front 505 2 = right 506 3 = back 507 4 = left 508 5 = bottom 509 6 = top 510 Example: 511 512 ON_TextureMapping mapping = ...; 513 const ON_Mesh* mesh = ...; 514 bool bLazy = true; 515 ON_SimpleArray<ON_3dPoint> T(mesh->VertexCount()); 516 T.SetCount(mesh->m_VertexCount()); 517 if ( !mapping.GetTextureCoordinates(mesh,3,3,&T[0].x,bLazy) ) 518 T.SetCount(0). 519 520 Returns: 521 True if successful. 522 */ 523 bool GetTextureCoordinates( 524 const ON_Mesh& mesh, 525 ON_SimpleArray<ON_3fPoint>& T, 526 const ON_Xform* mesh_xform = 0, 527 bool bLazy = false, 528 ON_SimpleArray<int>* Tside = 0 529 ) const; 530 531 bool GetTextureCoordinates( 532 const ON_Mesh& mesh, 533 ON_SimpleArray<ON_2fPoint>& T, 534 const ON_Xform* mesh_xform = 0, 535 bool bLazy = false, 536 ON_SimpleArray<int>* Tside = 0 537 ) const; 538 539 public: 540 // The only reliable and persistent way to reference texture 541 // mappings is by the mapping_id. If the mapping id is 542 // set to m_srfp_mapping_id, then all other mapping settings 543 // are ignored. 544 ON_UUID m_mapping_id; 545 546 // Runtime texture mapping table index. 547 // This value is NOT SAVED IN 3DM FILES. 548 // This value is constant for each runtime instance of Rhino, 549 // but can change each time a model is loaded or saved. 550 // Once a texture mapping is in the CRhinoDoc material table, 551 // its id and index never change in that instance of Rhino. 552 int m_mapping_index; 553 554 // The texture mapping name is for UI and user comfort. 555 // Duplicates are permitted. 556 ON_wString m_mapping_name; 557 558 ////////////////////////////////////////////////////////// 559 // 560 // Mapping types: 561 // 562 // You can either calculate texture coordinates based on 563 // the parameterization of the surface used to create a mesh, 564 // or project the natural parameterization from a mapping 565 // primitive, like a plane, sphere, box, or cylinder. 566 // 567 // Do not change TYPE enum values - they are saved in 3dm files. 568 // 569 enum TYPE 570 { 571 no_mapping = 0, 572 573 srfp_mapping = 1, // u,v = linear transform of surface params,w = 0 574 plane_mapping = 2, // u,v,w = 3d coordinates wrt frame 575 cylinder_mapping = 3, // u,v,w = logitude, height, radius 576 sphere_mapping = 4, // (u,v,w) = longitude,latitude,radius 577 box_mapping = 5, 578 mesh_mapping_primitive = 6, // m_mapping_primitive is an ON_Mesh 579 srf_mapping_primitive = 7, // m_mapping_primitive is an ON_Surface 580 brep_mapping_primitive = 8, // m_mapping_primitive is an ON_Brep 581 582 force_32bit_mapping_type = 0xFFFFFFFF 583 }; 584 585 TYPE m_type; 586 587 ////////////////////////////////////////////////////////// 588 // 589 // Projection: 590 // 591 // When a mapping primitive, like a plane, sphere, box, 592 // or cylinder, is used, there are two projection options. 593 // 594 // clspt_projection: world xyz maps to the point on the 595 // mapping primitive that is closest to xyz. 596 // In this case, ON_TextureMapping::Evaluate 597 // ignores the vector argument. 598 // 599 // ray_projection: world xyz + world vector defines a world line. 600 // The world line is intersected with the mapping 601 // primitive and the intersection point that is 602 // closest to the world xyz point is used to 603 // calculate the mapping parameters. 604 // 605 // The value of m_projection can be changed as needed. 606 // 607 // If m_type = srfp_mapping, then m_projection is ignored. 608 // 609 enum PROJECTION 610 { 611 no_projection = 0, 612 clspt_projection = 1, 613 ray_projection = 2, 614 force_32bit_mapping_projection = 0xFFFFFFFF 615 }; 616 617 PROJECTION m_projection; 618 619 ////////////////////////////////////////////////////////// 620 // 621 // Texture space 622 // 623 // When a mapping primitive is a box or a capped cylinder, 624 // there are two options for the mapping. Either the sides 625 // all map to (0,1)x(0,1) (so the either texture map appears 626 // on each side, or the sides map to distinct regions of the 627 // texture space. 628 // 629 enum TEXTURE_SPACE 630 { 631 single = 0, // sides and caps map to same texture space 632 divided = 1, // sides and caps map to distinct vertical 633 // regions of texture space. 634 // (0, 1/4, 2/4, 3/4, 1) for uncapped boxes. 635 // (0, 1/6, 2/6, 3/6, 4/6, 5/6, 1) for capped boxes. 636 // (0, 4/6, 5/6, 1) for capped cylinders. 637 force_32bit_texture_space = 0xFFFFFFFF 638 }; 639 640 TEXTURE_SPACE m_texture_space; 641 642 // The m_bCapped applies to planar, cylinder and box mappings. 643 // If m_bCapped is false, the cylinder or box is "infinite", if m_bCapped is true, they are finite. 644 // In planar mappings, m_bCapped=false means "the Z texture coordinate will always be 0.0" 645 // this is now the default behaviour in Rhino 5.0 - it's what users expect apparently. 646 bool m_bCapped; 647 648 ////////////////////////////////////////////////////////// 649 // 650 // For primitive based mappings, these transformations are 651 // used to map the world coordinate (x,y,z) point P and 652 // surface normal N before it is projected to the normalized 653 // mapping primitive. The surface normal transformation, 654 // m_Nxyz, is always calculated from m_Pxyz. It is a 655 // runtime setting that is not saved in 3dm files. 656 // If m_type is srfp_mapping, then m_Pxyz and m_Nxyz are 657 // ignored. 658 ON_Xform m_Pxyz; 659 ON_Xform m_Nxyz; 660 661 // Transform applied to mapping coordinate (u,v,w) to 662 // convert it into a texture coordinate. 663 ON_Xform m_uvw; 664 665 // Custom mapping primitive. 666 ON_Object* m_mapping_primitive; 667 668 static TYPE TypeFromInt( int i ); 669 static PROJECTION ProjectionFromInt( int i ); 670 static TEXTURE_SPACE TextureSpaceFromInt( int i); 671 672 ON__UINT32 MappingCRC() const; 673 }; 674 675 #if defined(ON_DLL_TEMPLATE) 676 // This stuff is here because of a limitation in the way Microsoft 677 // handles templates and DLLs. See Microsoft's knowledge base 678 // article ID Q168958 for details. 679 #pragma warning( push ) 680 #pragma warning( disable : 4231 ) 681 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_TextureMapping>; 682 ON_DLL_TEMPLATE template class ON_CLASS ON_ObjectArray<ON_TextureMapping>; 683 #pragma warning( pop ) 684 #endif 685 686 687 #endif 688 689