00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019
00021
00023
00024 ON_OBJECT_IMPLEMENT(ON_Material,ON_Object,"60B5DBBC-E660-11d3-BFE4-0010830122F0");
00025
00026 double ON_Material::m_max_shine = 255.0f;
00027
00028 double ON_Material::MaxShine()
00029 {
00030 return m_max_shine;
00031 }
00032
00033 void ON_Material::Default()
00034 {
00035 PurgeUserData();
00036
00037 m_material_index = 0;
00038 m_material_id = ON_nil_uuid;
00039 m_material_name.Destroy();
00040 m_flamingo_library.Destroy();
00041
00042 m_ambient.SetRGB( 0, 0, 0 );
00043 m_diffuse.SetRGB( 128, 128, 128 );
00044 m_emission.SetRGB( 0, 0, 0 );
00045 m_specular.SetRGB( 255, 255, 255 );
00046
00047
00048 m_reflection.SetRGB( 255, 255, 255 );
00049 m_transparent.SetRGB( 255, 255, 255 );
00050
00051 m_index_of_refraction = 1.0;
00052 m_reflectivity = 0.0;
00053
00054 m_shine = 0.0;
00055 m_transparency = 0.0;
00056
00057 m_bShared = false;
00058 m_bDisableLighting = false;
00059 m_reserved1[0] = 0;
00060 m_reserved1[1] = 0;
00061 #if defined(ON_64BIT_POINTER)
00062 m_reserved2[0] = 0;
00063 m_reserved2[1] = 0;
00064 m_reserved2[2] = 0;
00065 m_reserved2[3] = 0;
00066 #endif
00067
00068 m_textures.Destroy();
00069
00070 m_plugin_id = ON_nil_uuid;
00071
00072 m_material_channel.Destroy();
00073 }
00074
00075
00076 ON_Material::ON_Material()
00077 {
00078 Default();
00079 }
00080
00081 ON_Material::~ON_Material()
00082 {}
00083
00084 ON_BOOL32
00085 ON_Material::IsValid( ON_TextLog* text_log ) const
00086 {
00087 return true;
00088 }
00089
00090
00091 void
00092 ON_Material::Dump( ON_TextLog& dump ) const
00093 {
00094 const wchar_t* s;
00095 dump.Print("index = %d\n",MaterialIndex());
00096 dump.Print("id = "); dump.Print(m_material_id); dump.Print("\n");
00097
00098 s = m_material_name;
00099 if ( !s )
00100 s = L"";
00101 dump.Print("name = \"%ls\"\n",s);
00102
00103 dump.Print("ambient rgb = "); dump.PrintRGB( m_ambient ); dump.Print("\n");
00104 dump.Print("diffuse rgb = "); dump.PrintRGB( m_diffuse ); dump.Print("\n");
00105 dump.Print("emmisive rgb = "); dump.PrintRGB( m_emission ); dump.Print("\n");
00106 dump.Print("specular rgb = "); dump.PrintRGB( m_specular ); dump.Print("\n");
00107 dump.Print("reflection rgb = "); dump.PrintRGB( m_reflection ); dump.Print("\n");
00108 dump.Print("transparent rgb = "); dump.PrintRGB( m_transparent ); dump.Print("\n");
00109 dump.Print("shine = %g%%\n",100.0*m_shine/ON_Material::MaxShine() );
00110 dump.Print("transparency = %g%%\n",100.0*m_transparency);
00111 dump.Print("reflectivity = %g%%\n",100.0*m_reflectivity);
00112 dump.Print("index of refraction = %g\n",m_index_of_refraction);
00113
00114 dump.Print("plug-in id = "); dump.Print(m_plugin_id); dump.Print("\n");
00115 int i;
00116 for( i = 0; i < m_textures.Count(); i++ )
00117 {
00118 dump.Print("texture[%d]:\n",i);
00119 dump.PushIndent();
00120 m_textures[i].Dump(dump);
00121 dump.PopIndent();
00122 }
00123 }
00124
00125
00126 ON_UUID ON_Material::MaterialPlugInUuid() const
00127 {
00128 return m_plugin_id;
00129 }
00130
00131 void ON_Material::SetMaterialPlugInUuid( ON_UUID u )
00132 {
00133 m_plugin_id = u;
00134 }
00135
00136 ON_BOOL32 ON_Material::Write( ON_BinaryArchive& file ) const
00137 {
00138 bool rc = false;
00139 if ( file.Archive3dmVersion() <= 3 )
00140 {
00141
00142 rc = WriteV3Helper(file);
00143 }
00144 else
00145 {
00146
00147
00148
00149
00150 rc = file.Write3dmChunkVersion(2,0);
00151
00152
00153
00154
00155 if (rc) rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,3);
00156 if (rc)
00157 {
00158 for(;;)
00159 {
00160 if ( rc ) rc = file.WriteUuid(m_material_id);
00161 if ( rc ) rc = file.WriteInt(m_material_index);
00162 if ( rc ) rc = file.WriteString(m_material_name);
00163
00164 if ( rc ) rc = file.WriteUuid(m_plugin_id);
00165
00166 if ( rc ) rc = file.WriteColor( m_ambient );
00167 if ( rc ) rc = file.WriteColor( m_diffuse );
00168 if ( rc ) rc = file.WriteColor( m_emission );
00169 if ( rc ) rc = file.WriteColor( m_specular );
00170 if ( rc ) rc = file.WriteColor( m_reflection );
00171 if ( rc ) rc = file.WriteColor( m_transparent );
00172
00173 if ( rc ) rc = file.WriteDouble( m_index_of_refraction );
00174 if ( rc ) rc = file.WriteDouble( m_reflectivity );
00175 if ( rc ) rc = file.WriteDouble( m_shine );
00176 if ( rc ) rc = file.WriteDouble( m_transparency );
00177
00178 if ( !rc )
00179 break;
00180
00181
00182 rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00183 if (rc)
00184 {
00185 int i, count = m_textures.Count();
00186 rc = file.WriteInt(count);
00187 for ( i = 0; i < count && rc; i++ )
00188 {
00189 rc = file.WriteObject(&m_textures[i]);
00190 }
00191 if ( !file.EndWrite3dmChunk() )
00192 rc = false;
00193 }
00194
00195
00196 if (rc) rc = file.WriteString(m_flamingo_library);
00197
00198
00199 if (rc) rc = file.WriteArray(m_material_channel);
00200
00201
00202 rc = file.WriteBool(m_bShared);
00203 if (!rc) break;
00204 rc = file.WriteBool(m_bDisableLighting);
00205 if (!rc) break;
00206
00207 break;
00208 }
00209 if (!file.EndWrite3dmChunk() )
00210 rc = false;
00211 }
00212 }
00213 return rc;
00214 }
00215
00216 bool ON_Material::WriteV3Helper( ON_BinaryArchive& file ) const
00217 {
00218 int i;
00219
00220
00221 bool rc = file.Write3dmChunkVersion(1,1);
00222 if ( rc ) rc = file.WriteColor( m_ambient );
00223 if ( rc ) rc = file.WriteColor( m_diffuse );
00224 if ( rc ) rc = file.WriteColor( m_emission );
00225 if ( rc ) rc = file.WriteColor( m_specular );
00226 if ( rc ) rc = file.WriteDouble( Shine() );
00227 if ( rc ) rc = file.WriteDouble( m_transparency );
00228
00229 if ( rc ) rc = file.WriteChar( (unsigned char)1 );
00230 if ( rc ) rc = file.WriteChar( (unsigned char)1 );
00231
00232 if ( rc ) rc = file.WriteChar( (unsigned char)0 );
00233 if ( rc ) rc = file.WriteChar( (unsigned char)2 );
00234
00235 if ( rc ) rc = file.WriteColor( ON_Color(0,0,0) );
00236
00237 if (rc)
00238 {
00239
00240 short s = 0;
00241 if (rc) rc = file.WriteShort(s);
00242 if (rc) rc = file.WriteShort(s);
00243 if (rc) rc = file.WriteDouble(0.0);
00244 if (rc) rc = file.WriteDouble(1.0);
00245 }
00246
00247 ON_wString filename;
00248 int j = 0;
00249 i = FindTexture( NULL, ON_Texture::bitmap_texture );
00250 if ( i >= 0 )
00251 {
00252 const ON_Texture& tmap = m_textures[i];
00253 if ( tmap.m_filename.Length() > 0 )
00254 {
00255 filename = tmap.m_filename;
00256 j = ( ON_Texture::decal_texture == tmap.m_mode ) ? 2 : 1;
00257 }
00258 }
00259
00260
00261
00262
00263 if ( rc ) rc = file.WriteString(filename);
00264 if ( rc ) rc = file.WriteInt( j );
00265 if ( rc ) rc = file.WriteInt( 0 );
00266
00267 filename.Destroy();
00268 j = 0;
00269 double bump_scale = 1.0;
00270 i = FindTexture( NULL, ON_Texture::bump_texture );
00271 if ( i >= 0 )
00272 {
00273 const ON_Texture& tmap = m_textures[i];
00274 if ( tmap.m_filename.Length() > 0 )
00275 {
00276 filename = tmap.m_filename;
00277 j = ( ON_Texture::decal_texture == tmap.m_mode ) ? 2 : 1;
00278 bump_scale = tmap.m_bump_scale[1];
00279 }
00280 }
00281
00282
00283
00284
00285
00286 if ( rc ) rc = file.WriteString( filename );
00287 if ( rc ) rc = file.WriteInt( j );
00288 if ( rc ) rc = file.WriteInt( 0 );
00289 if ( rc ) rc = file.WriteDouble( bump_scale );
00290
00291 filename.Destroy();
00292 j = 0;
00293 i = FindTexture( NULL, ON_Texture::emap_texture );
00294 if ( i >= 0 )
00295 {
00296 const ON_Texture& tmap = m_textures[i];
00297 if ( tmap.m_filename.Length() > 0 )
00298 {
00299 filename = tmap.m_filename;
00300 j = ( ON_Texture::decal_texture == tmap.m_mode ) ? 2 : 1;
00301 }
00302 }
00303
00304
00305
00306
00307 if ( rc ) rc = file.WriteString( filename );
00308 if ( rc ) rc = file.WriteInt( j );
00309 if ( rc ) rc = file.WriteInt( 0 );
00310
00311 if ( rc ) rc = file.WriteInt( m_material_index );
00312
00313 if ( rc ) rc = file.WriteUuid( m_plugin_id );
00314 if ( rc ) rc = file.WriteString( m_flamingo_library );
00315 if ( rc ) rc = file.WriteString( m_material_name );
00316
00317
00318
00319 if (rc) rc = file.WriteUuid( m_material_id );
00320 if (rc) rc = file.WriteColor( m_reflection);
00321 if (rc) rc = file.WriteColor( m_transparent);
00322 if (rc) rc = file.WriteDouble( m_index_of_refraction );
00323
00324 return rc;
00325 }
00326
00327 ON_BOOL32 ON_Material::Read( ON_BinaryArchive& file )
00328 {
00329 Default();
00330 int major_version = 0;
00331 int minor_version = 0;
00332 bool rc = file.Read3dmChunkVersion(&major_version,&minor_version);
00333 if (rc)
00334 {
00335 if ( 1 == major_version )
00336 {
00337 rc = ReadV3Helper(file,minor_version);
00338 }
00339 else if ( 2 == major_version )
00340 {
00341
00342
00343
00344
00345
00346 rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00347 if (rc)
00348 {
00349 for(;;)
00350 {
00351 if ( rc ) rc = file.ReadUuid(m_material_id);
00352 if ( rc ) rc = file.ReadInt(&m_material_index);
00353 if ( rc ) rc = file.ReadString(m_material_name);
00354
00355 if ( rc ) rc = file.ReadUuid(m_plugin_id);
00356
00357 if ( rc ) rc = file.ReadColor( m_ambient );
00358 if ( rc ) rc = file.ReadColor( m_diffuse );
00359 if ( rc ) rc = file.ReadColor( m_emission );
00360 if ( rc ) rc = file.ReadColor( m_specular );
00361 if ( rc ) rc = file.ReadColor( m_reflection );
00362 if ( rc ) rc = file.ReadColor( m_transparent );
00363
00364 if ( rc
00365 && file.ArchiveOpenNURBSVersion() < 200912010
00366 && 128 == m_transparent.Red()
00367 && 128 == m_transparent.Green()
00368 && 128 == m_transparent.Blue()
00369 )
00370 {
00371
00372
00373
00374
00375 m_transparent = m_diffuse;
00376 }
00377
00378 if ( rc ) rc = file.ReadDouble( &m_index_of_refraction );
00379 if ( rc ) rc = file.ReadDouble( &m_reflectivity );
00380 if ( rc ) rc = file.ReadDouble( &m_shine );
00381 if ( rc ) rc = file.ReadDouble( &m_transparency );
00382
00383 if ( !rc )
00384 break;
00385
00386
00387 int texmajver = 0;
00388 int texminver = 0;
00389 rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&texmajver,&texminver);
00390 if (rc)
00391 {
00392 if ( 1 == texmajver )
00393 {
00394 int i, count = 0;
00395 rc = file.ReadInt(&count);
00396 if (rc) m_textures.Reserve(count);
00397 for ( i = 0; i < count && rc; i++ )
00398 {
00399 int trc = file.ReadObject(m_textures.AppendNew());
00400 if ( trc <= 0 )
00401 rc = false;
00402 else if ( trc > 1 )
00403 m_textures.Remove();
00404 }
00405 }
00406 if ( !file.EndRead3dmChunk() )
00407 rc = false;
00408 }
00409
00410 if ( rc && minor_version >= 1 )
00411 {
00412 rc = file.ReadString(m_flamingo_library);
00413 if ( !rc ) break;
00414
00415 if ( minor_version >= 2 )
00416 {
00417
00418 rc = file.ReadArray(m_material_channel);
00419 if (!rc) break;
00420
00421 if ( minor_version >= 3 )
00422 {
00423
00424 rc = file.ReadBool(&m_bShared);
00425 if (!rc) break;
00426 rc = file.ReadBool(&m_bDisableLighting);
00427 if (!rc) break;
00428 }
00429 }
00430
00431 }
00432
00433 break;
00434 }
00435 if (!file.EndRead3dmChunk() )
00436 rc = false;
00437 }
00438 }
00439 }
00440 return rc;
00441 }
00442
00443 bool ON_Material::ReadV3Helper( ON_BinaryArchive& file, int minor_version )
00444 {
00445 double shine = 0.0, transparency = 0.0;
00446 int i, j;
00447 bool rc = true;
00448 {
00449
00450 if ( rc ) rc = file.ReadColor( m_ambient );
00451 if ( rc ) rc = file.ReadColor( m_diffuse );
00452 if ( rc ) rc = file.ReadColor( m_emission );
00453 if ( rc ) rc = file.ReadColor( m_specular );
00454 if ( rc ) rc = file.ReadDouble( &shine );
00455 if ( rc ) SetShine(shine);
00456 if ( rc ) rc = file.ReadDouble( &transparency );
00457 if ( rc ) SetTransparency(transparency);
00458
00459 unsigned char obsolete_uc;
00460 if ( rc ) rc = file.ReadChar( &obsolete_uc );
00461 if ( rc ) rc = file.ReadChar( &obsolete_uc );
00462
00463 if ( rc ) rc = file.ReadChar( &obsolete_uc );
00464 if ( rc ) rc = file.ReadChar( &obsolete_uc );
00465
00466 ON_Color obsolete_color;
00467 if ( rc ) rc = file.ReadColor( obsolete_color );
00468
00469 if (rc)
00470 {
00471
00472 short s;
00473 double x;
00474 if (rc) rc = file.ReadShort(&s);
00475 if (rc) rc = file.ReadShort(&s);
00476 if (rc) rc = file.ReadDouble(&x);
00477 if (rc) rc = file.ReadDouble(&x);
00478 }
00479
00480 ON_wString str;
00481
00482 if ( rc ) rc = file.ReadString( str );
00483 i = 0;
00484 j = 0;
00485 if ( rc ) rc = file.ReadInt( &i );
00486
00487 if ( rc ) rc = file.ReadInt( &j );
00488
00489 if ( rc && !str.IsEmpty() )
00490 {
00491 ON_Texture& texture = m_textures[AddTexture(str,ON_Texture::bitmap_texture)];
00492 if ( 2 == i )
00493 {
00494 texture.m_mode = ON_Texture::decal_texture;
00495 }
00496 else
00497 {
00498 texture.m_mode = ON_Texture::modulate_texture;
00499 }
00500 }
00501
00502 if ( rc ) rc = file.ReadString( str );
00503 if ( rc ) rc = file.ReadInt( &i );
00504
00505 if ( rc ) rc = file.ReadInt( &j );
00506 double bump_scale = 0.0;
00507 if ( rc ) rc = file.ReadDouble( &bump_scale );
00508
00509 if ( rc && !str.IsEmpty() )
00510 {
00511 ON_Texture& texture = m_textures[AddTexture(str,ON_Texture::bump_texture)];
00512 if ( 2 == i )
00513 {
00514 texture.m_mode = ON_Texture::decal_texture;
00515 }
00516 else
00517 {
00518 texture.m_mode = ON_Texture::modulate_texture;
00519 }
00520 texture.m_bump_scale.Set(0.0,bump_scale);
00521 }
00522
00523 if ( rc ) rc = file.ReadString( str );
00524 if ( rc ) rc = file.ReadInt( &i );
00525
00526 if ( rc ) rc = file.ReadInt( &j );
00527
00528 if ( rc && !str.IsEmpty() )
00529 {
00530 ON_Texture& texture = m_textures[AddTexture(str,ON_Texture::emap_texture)];
00531 if ( 2 == i )
00532 {
00533 texture.m_mode = ON_Texture::decal_texture;
00534 }
00535 else
00536 {
00537 texture.m_mode = ON_Texture::modulate_texture;
00538 }
00539 }
00540
00541 if ( rc ) rc = file.ReadInt( &m_material_index );
00542
00543 if ( rc ) rc = file.ReadUuid( m_plugin_id );
00544 if ( rc ) rc = file.ReadString( m_flamingo_library );
00545 if ( rc ) rc = file.ReadString( m_material_name );
00546
00547 if ( minor_version >= 1 )
00548 {
00549
00550 if (rc) rc = file.ReadUuid( m_material_id );
00551 if (rc) rc = file.ReadColor( m_reflection);
00552 if (rc) rc = file.ReadColor( m_transparent);
00553 if (rc) rc = file.ReadDouble( &m_index_of_refraction );
00554 }
00555 else
00556 {
00557
00558 ON_CreateUuid(m_material_id);
00559 }
00560
00561 }
00562
00563 return rc;
00564 }
00565
00566 ON::object_type ON_Material::ObjectType() const
00567 {
00568 return ON::material_object;
00569 }
00570
00571 int ON_Material::FindTexture( const wchar_t* filename,
00572 ON_Texture::TYPE type,
00573 int i0
00574 ) const
00575 {
00576 int i, count = m_textures.Count();
00577 for (i = ((i0 < 0) ? 0 : (i0+1)); i < count; i++ )
00578 {
00579 if ( type != m_textures[i].m_type
00580 && type != ON_Texture::no_texture_type )
00581 {
00582 continue;
00583 }
00584 if ( filename && m_textures[i].m_filename.CompareNoCase(filename) )
00585 {
00586 continue;
00587 }
00588 return i;
00589 }
00590 return -1;
00591 }
00592
00593 int ON_Material::FindTexture( ON_UUID texture_id ) const
00594 {
00595 int i, count = m_textures.Count();
00596 for (i = 0; i < count; i++ )
00597 {
00598 if ( !ON_UuidCompare(&texture_id,&m_textures[i].m_texture_id) )
00599 return i;
00600 }
00601 return -1;
00602 }
00603
00604 int ON_Material::DeleteTexture(const wchar_t* filename,ON_Texture::TYPE type )
00605 {
00606 int deleted_count = 0;
00607 int i;
00608
00609 if ( !filename && type == ON_Texture::no_texture_type )
00610 {
00611 deleted_count = m_textures.Count();
00612 m_textures.Destroy();
00613 }
00614 else
00615 {
00616 for ( i = m_textures.Count()-1; i >= 0; i--)
00617 {
00618 if ( type != ON_Texture::no_texture_type && type != m_textures[i].m_type )
00619 continue;
00620 if ( filename && m_textures[i].m_filename.CompareNoCase(filename) )
00621 continue;
00622 m_textures.Remove(i);
00623 deleted_count++;
00624 }
00625 }
00626 return deleted_count;
00627 }
00628
00629 int ON_Material::AddTexture( const ON_Texture& tx )
00630 {
00631
00632 int i = FindTexture( tx.m_filename, tx.m_type );
00633 if ( i < 0 )
00634 {
00635 i = m_textures.Count();
00636 m_textures.Append(tx);
00637 }
00638 else
00639 {
00640 m_textures[i] = tx;
00641 }
00642 if ( ON_UuidIsNil(m_textures[i].m_texture_id) )
00643 {
00644 ON_CreateUuid(m_textures[i].m_texture_id);
00645 }
00646
00647 return i;
00648 }
00649
00650
00651 int ON_Material::AddTexture(const wchar_t* filename,ON_Texture::TYPE type)
00652 {
00653 int ti = FindTexture(NULL,type);
00654 if ( ti < 0 )
00655 {
00656 ti = m_textures.Count();
00657 m_textures.AppendNew();
00658 }
00659 if (ti >= 0 )
00660 {
00661 m_textures[ti].m_filename = filename;
00662 m_textures[ti].m_type = type;
00663 m_textures[ti].m_mode = ON_Texture::modulate_texture;
00664 m_textures[ti].m_magfilter = ON_Texture::linear_filter;
00665 ON_CreateUuid(m_textures[ti].m_texture_id);
00666 }
00667 return ti;
00668 }
00669
00670
00671 double ON_Material::Shine() const
00672 {
00673 return m_shine;
00674 }
00675
00676 void ON_Material::SetShine( double shine )
00677 {
00678 if ( shine < 0.0 )
00679 m_shine = 0.0;
00680 else if ( shine > m_max_shine)
00681 m_shine = m_max_shine;
00682 else
00683 m_shine = (float)shine;
00684 }
00685
00686
00687 double ON_Material::Transparency( ) const
00688 {
00689 return m_transparency;
00690 }
00691
00692 void ON_Material::SetTransparency( double transparency )
00693 {
00694 if ( transparency < 0.0 )
00695 m_transparency = 0.0f;
00696 else if ( transparency > 1.0)
00697 m_transparency = 1.0f;
00698 else
00699 m_transparency = (float)transparency;
00700 }
00701
00702 bool ON_Material::operator==( const ON_Material& src ) const
00703 {
00704 return Compare(src) ? false : true;
00705 }
00706
00707 bool ON_Material::operator!=( const ON_Material& src ) const
00708 {
00709 return Compare(src) ? true : false;
00710 }
00711
00712 static int CompareDouble( double a, double b )
00713 {
00714 return ( ( a < b ) ? -1 : ((a > b) ? 1 : 0) );
00715 }
00716
00717 static int CompareXform( const ON_Xform& a, const ON_Xform& b )
00718 {
00719 int i,j;
00720 const double* da = &a.m_xform[0][0];
00721 const double* db = &b.m_xform[0][0];
00722 i = 16;
00723 j = 0;
00724 while ( i-- && !j)
00725 {
00726 j = CompareDouble(*da++,*db++);
00727 }
00728
00729 return j;
00730 }
00731
00732 static int CompareTextureDoubles( size_t count, const double* a, const double* b )
00733 {
00734 while ( count-- )
00735 {
00736 if ( *a < *b )
00737 return -1;
00738 if ( *a > *b )
00739 return 1;
00740 a++;
00741 b++;
00742 }
00743 return 0;
00744 }
00745
00746 int ON_Texture::Compare( const ON_Texture& other ) const
00747 {
00748 int rc = ON_UuidCompare( &m_texture_id, &other.m_texture_id );
00749 while(!rc)
00750 {
00751 rc = m_mapping_channel_id - other.m_mapping_channel_id;
00752 if (rc) break;
00753
00754 rc = m_filename.CompareNoCase(other.m_filename);
00755 if (rc) break;
00756
00757 rc = ((int)m_bOn) - ((int)other.m_bOn);
00758 if (rc) break;
00759
00760 rc = ((int)m_type) - ((int)other.m_type);
00761 if (rc) break;
00762
00763 rc = ((int)m_mode) - ((int)other.m_mode);
00764 if (rc) break;
00765
00766 rc = ((int)m_minfilter) - ((int)other.m_minfilter);
00767 if (rc) break;
00768
00769 rc = ((int)m_magfilter) - ((int)other.m_magfilter);
00770 if (rc) break;
00771
00772 rc = ((int)m_wrapu) - ((int)other.m_wrapu);
00773 if (rc) break;
00774
00775 rc = ((int)m_wrapv) - ((int)other.m_wrapv);
00776 if (rc) break;
00777
00778 rc = ((int)m_wrapw) - ((int)other.m_wrapw);
00779 if (rc) break;
00780
00781 rc = CompareXform(m_uvw, other.m_uvw);
00782 if (rc) break;
00783
00784 rc = m_border_color.Compare(other.m_border_color);
00785 if (rc) break;
00786
00787 rc = m_transparent_color.Compare(other.m_transparent_color);
00788 if (rc) break;
00789
00790 rc = m_bump_scale.Compare(other.m_bump_scale);
00791 if (rc) break;
00792
00793 rc = CompareTextureDoubles( 1, &m_blend_constant_A, &other.m_blend_constant_A );
00794 if (rc) break;
00795
00796 rc = CompareTextureDoubles( sizeof(m_blend_A)/sizeof(m_blend_A[0]), m_blend_A, other.m_blend_A);
00797 if (rc) break;
00798
00799 rc = CompareTextureDoubles( sizeof(m_blend_RGB)/sizeof(m_blend_RGB[0]), m_blend_RGB, other.m_blend_RGB);
00800 if (rc) break;
00801
00802 break;
00803 }
00804
00805 return rc;
00806 }
00807
00808 int ON_Material::Compare( const ON_Material& other ) const
00809 {
00810
00811
00812 int rc = ON_UuidCompare( &m_material_id, &other.m_material_id );
00813 while(!rc)
00814 {
00815 rc = m_material_name.CompareNoCase( other.m_material_name );
00816 if (rc) break;
00817
00818 rc = m_ambient.Compare(other.m_ambient);
00819 if (rc) break;
00820
00821 rc = m_diffuse.Compare( other.m_diffuse );
00822 if (rc) break;
00823
00824 rc = m_diffuse.Compare( other.m_diffuse );
00825 if (rc) break;
00826
00827 rc = m_emission.Compare( other.m_emission );
00828 if (rc) break;
00829
00830 rc = m_specular.Compare( other.m_specular );
00831 if (rc) break;
00832
00833 rc = m_reflection.Compare( other.m_reflection );
00834 if (rc) break;
00835
00836 rc = m_transparent.Compare( other.m_transparent );
00837 if (rc) break;
00838
00839 rc = CompareDouble(m_index_of_refraction,other.m_index_of_refraction);
00840 if (rc) break;
00841
00842 rc = CompareDouble(m_reflectivity,other.m_reflectivity);
00843 if (rc) break;
00844
00845 rc = CompareDouble(m_shine,other.m_shine);
00846 if (rc) break;
00847
00848 rc = CompareDouble(m_transparency,other.m_transparency);
00849 if (rc) break;
00850
00851 rc = ON_UuidCompare( &m_plugin_id, &other.m_plugin_id );
00852 if (rc) break;
00853
00854 const int tcount = m_textures.Count();
00855 rc = tcount - other.m_textures.Count();
00856 int i;
00857 for ( i = 0; i < tcount && !rc; i++ )
00858 {
00859 rc = m_textures[i].Compare( other.m_textures[i] );
00860 }
00861 if (rc) break;
00862
00863
00864
00865 break;
00866 }
00867
00868 return rc;
00869 }
00870
00871 ON_Color ON_Material::Ambient() const
00872 {
00873 return m_ambient & 0x00FFFFFF;
00874 }
00875
00876 ON_Color ON_Material::Diffuse( ) const
00877 {
00878 return m_diffuse & 0x00FFFFFF;
00879 }
00880
00881 ON_Color ON_Material::Emission( ) const
00882 {
00883 return m_emission & 0x00FFFFFF;
00884 }
00885
00886 ON_Color ON_Material::Specular() const
00887 {
00888 return m_specular & 0x00FFFFFF;
00889 }
00890
00891 void ON_Material::SetAmbient( ON_Color c )
00892 {
00893 m_ambient = c;
00894 }
00895
00896 void ON_Material::SetDiffuse( ON_Color c )
00897 {
00898 m_diffuse = c ;
00899 }
00900
00901 void ON_Material::SetEmission( ON_Color c )
00902 {
00903 m_emission = c ;
00904 }
00905
00906 void ON_Material::SetSpecular( ON_Color c )
00907 {
00908 m_specular = c;
00909 }
00910
00911 int ON_Material::MaterialIndex() const
00912 {
00913 return m_material_index;
00914 }
00915
00916 void ON_Material::SetMaterialIndex( int i )
00917 {
00918 m_material_index = i;
00919 }
00920
00921 const wchar_t* ON_Material::MaterialName( ) const
00922 {
00923 return m_material_name;
00924 }
00925
00926 void ON_Material::SetMaterialName( const wchar_t* sMaterialName )
00927 {
00928 m_material_name = sMaterialName;
00929 }
00930
00932
00934
00935 ON_OBJECT_IMPLEMENT(ON_Texture,ON_Object,"D6FF106D-329B-4f29-97E2-FD282A618020");
00936
00937 ON_Texture::ON_Texture()
00938 {
00939 Default();
00940 }
00941
00942 ON_Texture::~ON_Texture()
00943 {
00944 }
00945
00946 ON_BOOL32 ON_Texture::IsValid( ON_TextLog* text_log ) const
00947 {
00948 if ( no_texture_type == m_type || force_32bit_texture_type == m_type )
00949 {
00950 if ( text_log )
00951 {
00952 text_log->Print("ON_Texture m_type has invalid value.\n");
00953 }
00954 return false;
00955 }
00956
00957
00958
00959 return true;
00960 }
00961
00962
00963 void ON_Texture::Dump( ON_TextLog& ) const
00964 {
00965
00966 }
00967
00968
00969 unsigned int ON_Texture::SizeOf() const
00970 {
00971 unsigned int sz = ON_Object::SizeOf();
00972 sz += sizeof(*this) - sizeof(ON_Object);
00973 sz += m_filename.Length()*sizeof(wchar_t);
00974 return sz;
00975 }
00976
00977
00978 ON_BOOL32 ON_Texture::Write(
00979 ON_BinaryArchive& binary_archive
00980 ) const
00981 {
00982 bool rc = binary_archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00983 if (rc)
00984 {
00985
00986 for(;;)
00987 {
00988
00989 rc = binary_archive.WriteUuid(m_texture_id);
00990 if (!rc) break;
00991 rc = binary_archive.WriteInt(m_mapping_channel_id);
00992 if (!rc) break;
00993 rc = binary_archive.WriteString(m_filename);
00994 if (!rc) break;
00995 rc = binary_archive.WriteBool(m_bOn);
00996 if (!rc) break;
00997 rc = binary_archive.WriteInt(m_type);
00998 if (!rc) break;
00999 rc = binary_archive.WriteInt(m_mode);
01000 if (!rc) break;
01001 rc = binary_archive.WriteInt(m_minfilter);
01002 if (!rc) break;
01003 rc = binary_archive.WriteInt(m_magfilter);
01004 if (!rc) break;
01005 rc = binary_archive.WriteInt(m_wrapu);
01006 if (!rc) break;
01007 rc = binary_archive.WriteInt(m_wrapv);
01008 if (!rc) break;
01009 rc = binary_archive.WriteInt(m_wrapw);
01010 if (!rc) break;
01011 rc = binary_archive.WriteXform(m_uvw);
01012 if (!rc) break;
01013 rc = binary_archive.WriteColor(m_border_color);
01014 if (!rc) break;
01015 rc = binary_archive.WriteColor(m_transparent_color);
01016 if (!rc) break;
01017 rc = binary_archive.WriteUuid(m_transparency_texture_id);
01018 if (!rc) break;
01019 rc = binary_archive.WriteInterval(m_bump_scale);
01020 if (!rc) break;
01021 rc = binary_archive.WriteDouble(m_blend_constant_A);
01022 if (!rc) break;
01023 rc = binary_archive.WriteDouble(4,m_blend_A);
01024 if (!rc) break;
01025 rc = binary_archive.WriteColor(m_blend_constant_RGB);
01026 if (!rc) break;
01027 rc = binary_archive.WriteDouble(4,m_blend_RGB);
01028 if (!rc) break;
01029 rc = binary_archive.WriteInt(m_blend_order);
01030 if (!rc) break;
01031
01032 break;
01033 }
01034
01035
01036 if ( !binary_archive.EndWrite3dmChunk() )
01037 rc = false;
01038 }
01039 return rc;
01040 }
01041
01042 ON_Texture::TYPE ON_Texture::TypeFromInt( int i )
01043 {
01044 ON_Texture::TYPE type = no_texture_type;
01045
01046 switch((unsigned int)i)
01047 {
01048 case no_texture_type:
01049 type = no_texture_type;
01050 break;
01051 case bitmap_texture:
01052 type = bitmap_texture;
01053 break;
01054 case bump_texture:
01055 type = bump_texture;
01056 break;
01057 case emap_texture:
01058 type = emap_texture;
01059 break;
01060 case transparency_texture:
01061 type = transparency_texture;
01062 break;
01063 case force_32bit_texture_type:
01064 type = force_32bit_texture_type;
01065 break;
01066 }
01067
01068 return type;
01069 }
01070
01071 ON_Texture::MODE ON_Texture::ModeFromInt( int i )
01072 {
01073 ON_Texture::MODE mode = no_texture_mode;
01074 switch((unsigned int)i)
01075 {
01076 case no_texture_mode:
01077 mode = no_texture_mode;
01078 break;
01079 case modulate_texture:
01080 mode = modulate_texture;
01081 break;
01082 case decal_texture:
01083 mode = decal_texture;
01084 break;
01085 case blend_texture:
01086 mode = blend_texture;
01087 break;
01088 case force_32bit_texture_mode:
01089 mode = force_32bit_texture_mode;
01090 break;
01091 }
01092 return mode;
01093 }
01094
01095 ON_Texture::FILTER ON_Texture::FilterFromInt( int i )
01096 {
01097 ON_Texture::FILTER filter = linear_filter;
01098 switch((unsigned int)i)
01099 {
01100 case nearest_filter:
01101 filter = nearest_filter;
01102 break;
01103 case linear_filter:
01104 filter = linear_filter;
01105 break;
01106 case force_32bit_texture_filter:
01107 filter = force_32bit_texture_filter;
01108 break;
01109 }
01110 return filter;
01111 }
01112
01113 ON_Texture::WRAP ON_Texture::WrapFromInt( int i )
01114 {
01115 ON_Texture::WRAP wrap = repeat_wrap;
01116
01117 switch((unsigned int)i)
01118 {
01119 case repeat_wrap:
01120 wrap = repeat_wrap;
01121 break;
01122 case clamp_wrap:
01123 wrap = clamp_wrap;
01124 break;
01125 case force_32bit_texture_wrap:
01126 wrap = force_32bit_texture_wrap;
01127 break;
01128 }
01129
01130 return wrap;
01131 }
01132
01133
01134
01135
01136
01137
01138 ON_BOOL32 ON_Texture::Read(
01139 ON_BinaryArchive& binary_archive
01140 )
01141 {
01142 Default();
01143
01144 int major_version = 0;
01145 int minor_version = 0;
01146 bool rc = binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01147 if (rc)
01148 {
01149
01150 if ( 1 != major_version )
01151 {
01152 rc = false;
01153 }
01154 else
01155 {
01156 int i;
01157 for(;;)
01158 {
01159
01160 rc = binary_archive.ReadUuid( m_texture_id );
01161 if (!rc) break;
01162
01163 rc = binary_archive.ReadInt( &m_mapping_channel_id );
01164 if (!rc) break;
01165
01166 rc = binary_archive.ReadString(m_filename);
01167 if (!rc) break;
01168
01169 rc = binary_archive.ReadBool(&m_bOn);
01170 if (!rc) break;
01171
01172 rc = binary_archive.ReadInt(&i);
01173 if (!rc) break;
01174 m_type = ON_Texture::TypeFromInt(i);
01175
01176 rc = binary_archive.ReadInt(&i);
01177 if (!rc) break;
01178 m_mode = ON_Texture::ModeFromInt(i);
01179
01180 rc = binary_archive.ReadInt(&i);
01181 if (!rc) break;
01182 m_minfilter = ON_Texture::FilterFromInt(i);
01183
01184 rc = binary_archive.ReadInt(&i);
01185 if (!rc) break;
01186 m_magfilter = ON_Texture::FilterFromInt(i);
01187
01188 rc = binary_archive.ReadInt(&i);
01189 if (!rc) break;
01190 m_wrapu = ON_Texture::WrapFromInt(i);
01191
01192 rc = binary_archive.ReadInt(&i);
01193 if (!rc) break;
01194 m_wrapv = ON_Texture::WrapFromInt(i);
01195
01196 rc = binary_archive.ReadInt(&i);
01197 if (!rc) break;
01198 m_wrapw = ON_Texture::WrapFromInt(i);
01199
01200 rc = binary_archive.ReadXform(m_uvw);
01201 if (!rc) break;
01202
01203 rc = binary_archive.ReadColor(m_border_color);
01204 if (!rc) break;
01205
01206 rc = binary_archive.ReadColor(m_transparent_color);
01207 if (!rc) break;
01208
01209 rc = binary_archive.ReadUuid(m_transparency_texture_id);
01210 if (!rc) break;
01211
01212 rc = binary_archive.ReadInterval(m_bump_scale);
01213 if (!rc) break;
01214
01215 rc = binary_archive.ReadDouble(&m_blend_constant_A);
01216 if (!rc) break;
01217 rc = binary_archive.ReadDouble(4,m_blend_A);
01218 if (!rc) break;
01219 rc = binary_archive.ReadColor(m_blend_constant_RGB);
01220 if (!rc) break;
01221 rc = binary_archive.ReadDouble(4,m_blend_RGB);
01222 if (!rc) break;
01223
01224 rc = binary_archive.ReadInt(&m_blend_order);
01225 if (!rc) break;
01226
01227
01228
01229 break;
01230 }
01231 }
01232
01233 if ( !binary_archive.EndRead3dmChunk() )
01234 rc = false;
01235 }
01236 return rc;
01237 }
01238
01239
01240 void ON_Texture::Default()
01241 {
01242 PurgeUserData();
01243 m_texture_id = ON_nil_uuid;
01244 m_mapping_channel_id = 0;
01245 m_filename.Destroy();
01246 m_filename_bRelativePath = false;
01247 m_bOn = true;
01248 m_type = bitmap_texture;
01249 m_mode = modulate_texture;
01250 m_minfilter = linear_filter;
01251 m_magfilter = linear_filter;
01252 m_wrapu = repeat_wrap;
01253 m_wrapv = repeat_wrap;
01254 m_wrapw = repeat_wrap;
01255 m_uvw.Identity();
01256 m_border_color = ON_UNSET_COLOR;
01257 m_transparent_color = ON_UNSET_COLOR;
01258 m_transparency_texture_id = ON_nil_uuid;
01259 m_bump_scale.Set(0.0,1.0);
01260 m_blend_constant_A = 1.0;
01261 m_blend_A[0] = m_blend_A[1] = 1.0; m_blend_A[2] = m_blend_A[3] = 0.0;
01262 m_blend_constant_RGB.SetRGB(0,0,0);
01263 m_blend_RGB[0] = m_blend_RGB[1] = 1.0; m_blend_RGB[2] = m_blend_RGB[3] = 0.0;
01264 m_blend_order = 0;
01265 m_runtime_ptr_id = ON_nil_uuid;
01266 m_runtime_ptr = 0;
01267 }
01268
01269
01270 ON_OBJECT_IMPLEMENT(ON_TextureMapping,ON_Object,"32EC997A-C3BF-4ae5-AB19-FD572B8AD554");
01271
01272
01273 ON_TextureMapping::TYPE ON_TextureMapping::TypeFromInt(int i)
01274 {
01275 ON_TextureMapping::TYPE t;
01276 switch(i)
01277 {
01278 case srfp_mapping:
01279 t = srfp_mapping;
01280 break;
01281 case plane_mapping:
01282 t = plane_mapping;
01283 break;
01284 case cylinder_mapping:
01285 t = cylinder_mapping;
01286 break;
01287 case sphere_mapping:
01288 t = sphere_mapping;
01289 break;
01290 case box_mapping:
01291 t = box_mapping;
01292 break;
01293 case mesh_mapping_primitive:
01294 t = mesh_mapping_primitive;
01295 break;
01296 case srf_mapping_primitive:
01297 t = srf_mapping_primitive;
01298 break;
01299 case brep_mapping_primitive:
01300 t = brep_mapping_primitive;
01301 break;
01302 default:
01303 t = no_mapping;
01304 break;
01305 }
01306 return t;
01307 }
01308
01309 ON_TextureMapping::PROJECTION ON_TextureMapping::ProjectionFromInt(int i)
01310 {
01311 ON_TextureMapping::PROJECTION p;
01312 switch(i)
01313 {
01314 case clspt_projection:
01315 p = clspt_projection;
01316 break;
01317 case ray_projection:
01318 p = ray_projection;
01319 break;
01320 default:
01321 p = no_projection;
01322 break;
01323 }
01324 return p;
01325 }
01326
01327 ON_TextureMapping::TEXTURE_SPACE ON_TextureMapping::TextureSpaceFromInt(int i)
01328 {
01329 ON_TextureMapping::TEXTURE_SPACE ts = single;
01330
01331 switch(i)
01332 {
01333 case single:
01334 ts = single;
01335 break;
01336 case divided:
01337 ts = divided;
01338 break;
01339 }
01340 return ts;
01341 }
01342
01343 ON_TextureMapping::ON_TextureMapping()
01344 {
01345 m_mapping_primitive = 0;
01346 Default();
01347 }
01348
01349 ON_TextureMapping::~ON_TextureMapping()
01350 {
01351 if ( m_mapping_primitive )
01352 {
01353 delete m_mapping_primitive;
01354 m_mapping_primitive = 0;
01355 }
01356 }
01357
01358
01359
01360 ON_TextureMapping::ON_TextureMapping(const ON_TextureMapping& src)
01361 : ON_Object(src)
01362 {
01363 m_mapping_id = src.m_mapping_id;
01364 m_mapping_index = src.m_mapping_index;
01365 m_mapping_name = src.m_mapping_name;
01366 m_type = src.m_type;
01367 m_projection = src.m_projection;
01368 m_bCapped = src.m_bCapped;
01369 m_texture_space = src.m_texture_space;
01370 m_Pxyz = src.m_Pxyz;
01371 m_Nxyz = src.m_Nxyz;
01372 m_uvw = src.m_uvw;
01373 m_mapping_primitive = ( src.m_mapping_primitive )
01374 ? src.m_mapping_primitive->Duplicate()
01375 : 0;
01376 }
01377
01378 ON_TextureMapping& ON_TextureMapping::operator=(const ON_TextureMapping& src)
01379 {
01380 if ( this != &src )
01381 {
01382 if ( m_mapping_primitive )
01383 {
01384 delete m_mapping_primitive;
01385 m_mapping_primitive = 0;
01386 }
01387 ON_Object::operator=(src);
01388 m_mapping_id = src.m_mapping_id;
01389 m_mapping_index = src.m_mapping_index;
01390 m_mapping_name = src.m_mapping_name;
01391 m_type = src.m_type;
01392 m_projection = src.m_projection;
01393 m_bCapped = src.m_bCapped;
01394 m_texture_space = src.m_texture_space;
01395 m_Pxyz = src.m_Pxyz;
01396 m_Nxyz = src.m_Nxyz;
01397 m_uvw = src.m_uvw;
01398 if ( src.m_mapping_primitive )
01399 m_mapping_primitive = src.m_mapping_primitive->Duplicate();
01400 }
01401 return *this;
01402 }
01403
01404 void ON_TextureMapping::Default()
01405 {
01406 PurgeUserData();
01407 if ( m_mapping_primitive )
01408 {
01409 delete m_mapping_primitive;
01410 m_mapping_primitive = 0;
01411 }
01412
01413 m_mapping_id = ON_nil_uuid;
01414 m_mapping_index = 0;
01415 m_mapping_name.Destroy();
01416 m_type = no_mapping;
01417 m_projection = no_projection;
01418 m_texture_space = single;
01419 m_Pxyz.Identity();
01420 m_Nxyz.Identity();
01421 m_uvw.Identity();
01422 m_bCapped = false;
01423 }
01424
01425 ON_BOOL32 ON_TextureMapping::IsValid( ON_TextLog* text_log ) const
01426 {
01427 if ( m_type != ON_TextureMapping::TypeFromInt(m_type) )
01428 {
01429 if ( text_log )
01430 {
01431 text_log->Print("ON_TextureMapping m_type = %d is not a valid value.\n",m_type);
01432 }
01433 return false;
01434 }
01435
01436 if ( m_projection != ON_TextureMapping::ProjectionFromInt(m_projection) )
01437 {
01438 if ( text_log )
01439 {
01440 text_log->Print("ON_TextureMapping m_projection = %d is not a valid value.\n",m_projection);
01441 }
01442 return false;
01443 }
01444
01445 if (m_texture_space != ON_TextureMapping::TextureSpaceFromInt(m_texture_space))
01446 {
01447 if (text_log)
01448 {
01449 text_log->Print("ON_TextureMapping m_texture_space = %d is not a valid value.\n",m_texture_space);
01450 }
01451 return false;
01452 }
01453
01454 return true;
01455 }
01456
01457 void ON_TextureMapping::Dump( ON_TextLog& text_log ) const
01458 {
01459 text_log.Print("Texture mapping id: "); text_log.Print(m_mapping_id); text_log.Print("\n");
01460 text_log.PushIndent();
01461
01462 text_log.Print("type: ");
01463 switch(m_type)
01464 {
01465 case no_mapping:
01466 text_log.Print("no mapping\n");
01467 break;
01468 case plane_mapping:
01469 text_log.Print("plane mapping\n");
01470 break;
01471 case cylinder_mapping:
01472 text_log.Print("cylinder mapping\n");
01473 break;
01474 case sphere_mapping:
01475 text_log.Print("sphere mapping\n");
01476 break;
01477 case box_mapping:
01478 text_log.Print("box mapping\n");
01479 break;
01480 default:
01481 text_log.Print("%d\n",m_type);
01482 break;
01483 }
01484
01485 text_log.Print("projection: ");
01486 switch(m_projection)
01487 {
01488 case no_projection:
01489 text_log.Print("no projection\n");
01490 break;
01491 case clspt_projection:
01492 text_log.Print("closest point to mesh vertex\n");
01493 break;
01494 case ray_projection:
01495 text_log.Print("mesh normal ray intersection\n");
01496 break;
01497 default:
01498 text_log.Print("%d\n",m_projection);
01499 break;
01500 }
01501
01502 text_log.Print("texture_space: ");
01503 switch(m_texture_space)
01504 {
01505 case single:
01506 text_log.Print("single texture space\n");
01507 break;
01508 case clspt_projection:
01509 text_log.Print("divided texture space\n");
01510 break;
01511 default:
01512 text_log.Print("%d\n",m_texture_space);
01513 break;
01514 }
01515
01516 text_log.Print("XYZ point transformation:\n");
01517 text_log.PushIndent();
01518 text_log.Print(m_Pxyz);
01519 text_log.PopIndent();
01520
01521 text_log.Print("XYZ normal transformation:\n");
01522 text_log.PushIndent();
01523 text_log.Print(m_Nxyz);
01524 text_log.PopIndent();
01525
01526 text_log.Print("UVW transformation:\n");
01527 text_log.PushIndent();
01528 text_log.Print(m_uvw);
01529 text_log.PopIndent();
01530
01531 text_log.PopIndent();
01532 }
01533
01534 unsigned int ON_TextureMapping::SizeOf() const
01535 {
01536 unsigned int sz = ON_Object::SizeOf();
01537 sz = sizeof(*this) - sizeof(ON_Object);
01538 return sz;
01539 }
01540
01541 bool ON_TextureMapping::ReverseTextureCoordinate( int dir )
01542 {
01543 bool rc = false;
01544 if ( 0 <= dir && dir <= 3 )
01545 {
01546 ON_Xform x(1.0);
01547 x.m_xform[dir][dir] = -1.0;
01548 x.m_xform[dir][3] = 1.0;
01549 m_uvw = x*m_uvw;
01550 rc = true;
01551 }
01552 return rc;
01553 }
01554
01555 bool ON_TextureMapping::SwapTextureCoordinate( int i, int j )
01556 {
01557 bool rc = false;
01558 if (i!=j && 0 <= i && i <= 3 && 0 <= j && j <= 3)
01559 {
01560 ON_Xform x(1.0);
01561 x.m_xform[i][i] = x.m_xform[j][j] = 0.0;
01562 x.m_xform[i][j] = x.m_xform[j][i] = 1.0;
01563 m_uvw = x*m_uvw;
01564 rc = true;
01565 }
01566 return rc;
01567 }
01568
01569 bool ON_TextureMapping::TileTextureCoordinate( int dir, double count, double offset )
01570 {
01571 bool rc = false;
01572 if ( 0 <= dir && dir <= 3 && 0.0 != count && ON_IsValid(count) && ON_IsValid(offset) )
01573 {
01574 ON_Xform x(1.0);
01575 x.m_xform[dir][dir] = count;
01576 x.m_xform[dir][3] = offset;
01577 m_uvw = x*m_uvw;
01578 rc = true;
01579 }
01580 return rc;
01581 }
01582
01583
01584 bool ON_Texture::ReverseTextureCoordinate( int dir )
01585 {
01586 bool rc = false;
01587 if ( 0 <= dir && dir <= 3 )
01588 {
01589 ON_Xform x(1.0);
01590 x.m_xform[dir][dir] = -1.0;
01591 x.m_xform[dir][3] = 1.0;
01592 m_uvw = x*m_uvw;
01593 rc = true;
01594 }
01595 return rc;
01596 }
01597
01598 bool ON_Texture::SwapTextureCoordinate( int i, int j )
01599 {
01600 bool rc = false;
01601 if (i!=j && 0 <= i && i <= 3 && 0 <= j && j <= 3)
01602 {
01603 ON_Xform x(1.0);
01604 x.m_xform[i][i] = x.m_xform[j][j] = 0.0;
01605 x.m_xform[i][j] = x.m_xform[j][i] = 1.0;
01606 m_uvw = x*m_uvw;
01607 rc = true;
01608 }
01609 return rc;
01610 }
01611
01612 bool ON_Texture::TileTextureCoordinate( int dir, double count, double offset )
01613 {
01614 bool rc = false;
01615 if ( 0 <= dir && dir <= 3 && 0.0 != count && ON_IsValid(count) && ON_IsValid(offset) )
01616 {
01617 ON_Xform x(1.0);
01618 x.m_xform[dir][dir] = count;
01619 x.m_xform[dir][3] = offset;
01620 m_uvw = x*m_uvw;
01621 rc = true;
01622 }
01623 return rc;
01624 }
01625
01626 bool ON_Texture::IsTiled( int dir, double* count, double* offset ) const
01627 {
01628 if ( count )
01629 *count = 1.0;
01630 if ( offset )
01631 *offset = 0.0;
01632
01633 if ( 0 <= dir && dir <= 3 )
01634 {
01635 int row0=-1, row, col;
01636 for ( row = 0; row < 3; row++ )
01637 {
01638 for ( col = 0; col < 3; col++ )
01639 {
01640 if ( col != dir && 0.0 != m_uvw.m_xform[row][col] )
01641 break;
01642 }
01643 if ( 3 == col )
01644 {
01645 if ( -1 == row0 )
01646 {
01647 row0 = row;
01648 }
01649 else
01650 return false;
01651 }
01652 }
01653 if ( row0 >= 0 )
01654 {
01655 if (count)
01656 *count = m_uvw.m_xform[row0][dir];
01657 if ( offset )
01658 *offset = m_uvw.m_xform[row0][3];
01659 return true;
01660 }
01661 }
01662
01663 return false;
01664 }
01665
01666 static const double on__overflow_tol = 1.0e100;
01667
01668 static
01669 int BestHitHelper(double t0, double t1)
01670 {
01671 return ((t0 < 0.0 && t1 > t0) || (0.0 <= t1 && t1 < t0)) ? 1 : 0;
01672 }
01673
01674 static
01675 int IntersectBoxRayHelper(const ON_3dPoint& rst, const ON_3dVector& n, int dir, double* s)
01676 {
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687 double nx = (&n.x)[dir];
01688 ON_3dPoint Q;
01689 double t,t0,t1;
01690
01691
01692 t = fabs(nx)*on__overflow_tol;
01693 t0 = (-1.0 - (&rst.x)[dir]);
01694 t1 = ( 1.0 - (&rst.x)[dir]);
01695 if ( fabs(t0) >= t || fabs(t1) >= t )
01696 {
01697 *s = ON_UNSET_VALUE;
01698 return 0;
01699 }
01700
01701 t0 /= nx;
01702 Q = rst + t0*n;
01703 if ( dir )
01704 {
01705 t = Q.x;
01706 Q.x = Q[dir];
01707 Q[dir] = t;
01708 }
01709 if ( fabs(Q.x+1.0) > ON_SQRT_EPSILON
01710 || Q.y < -(1.0+ON_SQRT_EPSILON) || Q.y > (1.0+ON_SQRT_EPSILON)
01711 || Q.z < -(1.0+ON_SQRT_EPSILON) || Q.z > (1.0+ON_SQRT_EPSILON)
01712 )
01713 {
01714
01715
01716 t0 = ON_UNSET_VALUE;
01717 }
01718
01719 t1 /= nx;
01720 Q = rst + t1*n;
01721 if ( dir )
01722 {
01723 t = Q.x;
01724 Q.x = Q[dir];
01725 Q[dir] = t;
01726 }
01727 if ( fabs(Q.x-1.0) > ON_SQRT_EPSILON
01728 || Q.y < -(1.0+ON_SQRT_EPSILON) || Q.y > (1.0+ON_SQRT_EPSILON)
01729 || Q.z < -(1.0+ON_SQRT_EPSILON) || Q.z > (1.0+ON_SQRT_EPSILON)
01730 )
01731 {
01732
01733
01734 t1 = ON_UNSET_VALUE;
01735 if ( ON_UNSET_VALUE == t0 )
01736 {
01737 *s = ON_UNSET_VALUE;
01738 return 0;
01739 }
01740 }
01741
01742 int rc;
01743 if ( ON_UNSET_VALUE == t0 || 1 == BestHitHelper(t0,t1) )
01744 {
01745 rc = 2 + 2*dir;
01746 *s = t1;
01747 }
01748 else
01749 {
01750 rc = 1 + 2*dir;
01751 *s = t0;
01752 }
01753 return rc;
01754 }
01755
01756
01757 int ON_TextureMapping::EvaluatePlaneMapping(
01758 const ON_3dPoint& P,
01759 const ON_3dVector& N,
01760 ON_3dPoint* T
01761 ) const
01762 {
01763
01764
01765
01766
01767 ON_3dPoint rst(m_Pxyz*P);
01768
01769 if ( ray_projection == m_projection )
01770 {
01771 ON_3dVector n(m_Nxyz*N);
01772 if ( fabs(rst.z) < fabs(n.z)*on__overflow_tol )
01773 {
01774 double t = -rst.z/n.z;
01775 rst.x = rst.x + t*n.x;
01776 rst.y = rst.y + t*n.y;
01777 }
01778 }
01779
01780
01781
01782 rst.x = 0.5*rst.x + 0.5;
01783 rst.y = 0.5*rst.y + 0.5;
01784
01785
01786 *T = m_uvw*rst;
01787
01788
01789 if (!m_bCapped)
01790 T->z = 0.0;
01791
01792 return 1;
01793 }
01794
01795 int ON_TextureMapping::EvaluateSphereMapping(
01796 const ON_3dPoint& P,
01797 const ON_3dVector& N,
01798 ON_3dPoint* T
01799 ) const
01800 {
01801
01802
01803
01804
01805 ON_3dPoint rst(m_Pxyz*P);
01806 const double r = ((const ON_3dVector*)(&rst.x))->Length();
01807 double t0, t1;
01808
01809 if ( ray_projection == m_projection )
01810 {
01811 ON_3dVector n(m_Nxyz*N);
01812
01813
01814 int rc = ON_SolveQuadraticEquation( (n.x*n.x+n.y*n.y+n.z*n.z),
01815 2.0*(rst.x*n.x+rst.y*n.y+rst.z*n.z),
01816 (rst.x*rst.x+rst.y*rst.y+rst.z*rst.z) - 1.0,
01817 &t0, &t1 );
01818 if (rc >= 0 )
01819 {
01820 if ( 2 != rc && 1 == BestHitHelper(t0,t1) )
01821 {
01822 t0 = t1;
01823 }
01824 rst = rst + t0*n;
01825 }
01826 }
01827
01828
01829 double longitude = (0.0 != rst.y || 0.0 != rst.x)
01830 ? atan2(rst.y,rst.x)
01831 : 0.0;
01832 double latitude = (0.0 != rst.z)
01833 ? atan2(rst.z,((const ON_2dVector*)(&rst.x))->Length())
01834 : 0.0;
01835 if ( latitude > ON_PI )
01836 latitude -= 2.0*ON_PI;
01837
01838
01839 rst.x = 0.5*longitude/ON_PI;
01840 if ( rst.x < -ON_EPSILON )
01841 rst.x += 1.0;
01842 else if (rst.x < 0.0)
01843 rst.x = 0.0;
01844 else if (rst.x > 1.0)
01845 rst.x = 1.0;
01846
01847
01848 rst.y = latitude/ON_PI + 0.5;
01849 if ( rst.y <= 0.0 )
01850 rst.y = 0.0;
01851 else if ( rst.y > 1.0 )
01852 rst.y = 1.0;
01853
01854
01855 rst.z = r;
01856
01857
01858 *T = m_uvw*rst;
01859
01860 return 1;
01861 }
01862
01863 int ON_TextureMapping::EvaluateCylinderMapping(
01864 const ON_3dPoint& P,
01865 const ON_3dVector& N,
01866 ON_3dPoint* T
01867 ) const
01868 {
01869
01870
01871
01872
01873
01874 ON_3dPoint rst(m_Pxyz*P);
01875
01876 ON_3dPoint Q;
01877 const double r = ((const ON_2dVector*)(&rst.x))->Length();
01878 double t, t0, t1;
01879 int side0, side1;
01880 PROJECTION mapping_proj = m_projection;
01881
01882 side0 = 0;
01883 if ( ON_TextureMapping::ray_projection == mapping_proj )
01884 {
01885 ON_3dVector n(m_Nxyz*N);
01886 t = 0.0;
01887
01888 if ( m_bCapped )
01889 {
01890
01891
01892
01893 t = fabs(n.z)*on__overflow_tol;
01894 if ( fabs(1.0+rst.z) < t && fabs(1.0-rst.z) < t )
01895 {
01896 side0 = 2;
01897 side1 = 3;
01898
01899 t0 = (-1.0 - rst.z)/n.z;
01900 Q = rst + t0*n;
01901 if ( fabs(1.0+Q.z) > ON_SQRT_EPSILON
01902 || (Q.x*Q.x + Q.y*Q.y) > 1.0 + 2.0*ON_SQRT_EPSILON + ON_EPSILON )
01903 {
01904
01905
01906 side0 = 0;
01907 }
01908
01909 t1 = ( 1.0 - rst.z)/n.z;
01910 Q = rst + t1*n;
01911 if ( fabs(1.0-Q.z) > ON_SQRT_EPSILON
01912 || (Q.x*Q.x + Q.y*Q.y) > 1.0 + 2.0*ON_SQRT_EPSILON + ON_EPSILON )
01913 {
01914
01915
01916 side1 = 0;
01917 }
01918 if ( 0 == side0 || 1 == BestHitHelper(t0,t1) )
01919 {
01920 side0 = side1;
01921 t = t1;
01922 }
01923 else
01924 {
01925 t = t0;
01926 }
01927 }
01928 }
01929
01930
01931 int rc = ON_SolveQuadraticEquation( (n.x*n.x+n.y*n.y),
01932 2.0*(rst.x*n.x+rst.y*n.y),
01933 (rst.x*rst.x+rst.y*rst.y) - 1.0,
01934 &t0, &t1 );
01935 if (rc >= 0 )
01936 {
01937 if ( 2 != rc && 1 == BestHitHelper(t0,t1) )
01938 {
01939 t0 = t1;
01940 }
01941 if ( 0 == side0 )
01942 {
01943
01944
01945 side0 = 1;
01946 rst = rst + t0*n;
01947 }
01948 else if ( 1 != BestHitHelper(t0,t) )
01949 {
01950
01951
01952
01953
01954 t1 = rst.z + t0*n.z;
01955 if ( t1 >= -(1.0+ON_SQRT_EPSILON) && t1 <= 1.0+ON_SQRT_EPSILON )
01956 {
01957
01958 side0 = 1;
01959 rst.x = rst.x + t0*n.x;
01960 rst.y = rst.y + t0*n.y;
01961 rst.x = t1;
01962 }
01963 }
01964 }
01965
01966 if ( side0 > 1 )
01967 {
01968
01969 rst = rst + t*n;
01970 }
01971 }
01972
01973 if ( m_bCapped && 0 == side0 )
01974 {
01975 if ( fabs(rst.z) > 1.0+ON_SQRT_EPSILON )
01976 {
01977 if ( fabs(rst.z) > r )
01978 {
01979 side0 = (rst.z < 0.0) ? 2 : 3;
01980 }
01981 }
01982 else if ( r <= 1.001 )
01983 {
01984
01985
01986
01987 ON_3dVector n(m_Nxyz*N);
01988 if ( ( fabs(n.z) > fabs(n.x) && fabs(n.z) > fabs(n.y) ) )
01989 {
01990 side0 = (n.z < 0.0) ? 2 : 3;
01991 }
01992 }
01993 }
01994
01995 if ( 2 == side0 || 3 == side0 )
01996 {
01997
01998
01999
02000 if ( 2 == side0 )
02001 {
02002
02003
02004
02005
02006 rst.x = -rst.x;
02007 }
02008
02009 if ( ON_TextureMapping::divided == m_texture_space )
02010 {
02011 if ( r >= 1.0-ON_SQRT_EPSILON )
02012 {
02013 rst.x /= (r+ON_SQRT_EPSILON);
02014 rst.y /= (r+ON_SQRT_EPSILON);
02015 }
02016 }
02017 else if ( r > 1.0 )
02018 {
02019 rst.x /= r;
02020 rst.y /= r;
02021 }
02022
02023
02024
02025 rst.x = 0.5*rst.x + 0.5;
02026 if ( rst.x < 0.0) rst.x = 0.0; else if (rst.x > 1.0) rst.x = 1.0;
02027 rst.y = 0.5*rst.y + 0.5;
02028 if ( rst.y < 0.0) rst.y = 0.0; else if (rst.y > 1.0) rst.y = 1.0;
02029
02030 if ( ON_TextureMapping::divided == m_texture_space )
02031 {
02032
02033
02034 rst.x = (2.0 + side0 + rst.x)/6.0;
02035 }
02036 }
02037 else
02038 {
02039
02040
02041
02042 t = (0.0 != rst.y || 0.0 != rst.x) ? atan2(rst.y,rst.x) : 0.0;
02043 rst.x = 0.5*t/ON_PI;
02044 if ( rst.x < -ON_EPSILON )
02045 rst.x += 1.0;
02046 else if (rst.x < 0.0 )
02047 rst.x = 0.0;
02048 else if (rst.x > 1.0 )
02049 rst.x = 1.0;
02050
02051 if ( ON_TextureMapping::divided == m_texture_space )
02052 {
02053
02054 rst.x *= 2.0;
02055 rst.x /= 3.0;
02056 }
02057
02058
02059 rst.y = 0.5*rst.z + 0.5;
02060 if ( m_bCapped )
02061 {
02062
02063 if ( rst.y < 0.0 ) rst.y = 0.0; else if ( rst.y > 1.0 ) rst.y = 1.0;
02064 }
02065 side0 = 1;
02066 }
02067 rst.z = r;
02068
02069 *T = m_uvw*rst;
02070
02071 return side0;
02072 }
02073
02074 int ON_TextureMapping::EvaluateBoxMapping(
02075 const ON_3dPoint& P,
02076 const ON_3dVector& N,
02077 ON_3dPoint* T
02078 ) const
02079 {
02080
02081
02082
02083
02084
02085 ON_3dPoint rst(m_Pxyz*P);
02086
02087 ON_3dVector n(m_Nxyz*N);
02088 n.Unitize();
02089
02090 int side0, side1;
02091 double t0, t1;
02092
02093 side0 = 0;
02094 t0 = 0.0;
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104 if ( ON_TextureMapping::ray_projection == m_projection )
02105 {
02106
02107 if ( m_bCapped )
02108 {
02109
02110 side0 = IntersectBoxRayHelper(rst,n,2,&t0);
02111 }
02112
02113 side1 = IntersectBoxRayHelper(rst,n,0,&t1);
02114 if ( 0 == side0 || 1 == BestHitHelper(t0,t1) )
02115 {
02116 side0 = side1;
02117 t0 = t1;
02118 }
02119
02120 side1 = IntersectBoxRayHelper(rst,n,1,&t1);
02121 if ( 0 == side0 || 1 == BestHitHelper(t0,t1) )
02122 {
02123 side0 = side1;
02124 t0 = t1;
02125 }
02126 if ( 0 != side0 )
02127 {
02128
02129 rst = rst + t0*n;
02130 }
02131 }
02132
02133 if ( 0 == side0 )
02134 {
02135
02136 side1 = (fabs(rst.x) >= fabs(rst.y)) ? 0 : 1;
02137 if ( m_bCapped && fabs(rst.z) > fabs(((double*)&rst.x)[side1]) )
02138 side1 = 2;
02139 t1 = (&rst.x)[side1];
02140 if ( t1 < 0.0 )
02141 {
02142 side0 = 2*side1 + 1;
02143 }
02144 else
02145 {
02146 side0 = 2*side1 + 2;
02147 }
02148
02149
02153
02154 side1 = ( fabs(n.x) >= fabs(n.y) ) ? 0 : 1;
02155 if ( m_bCapped && fabs(n.z) > fabs((&n.x)[side1]))
02156 {
02157 side1 = 2;
02158 }
02159 t1 = n[side1];
02160 if ( 0.0 != t1 )
02161 {
02162 if ( t1 < 0.0 )
02163 side0 = 2*side1 + 1;
02164 else if ( t1 > 0.0 )
02165 side0 = 2*side1 + 2;
02166 }
02167 }
02168
02169 double shift = 0.0;
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179 switch(side0)
02180 {
02181 case 1:
02182 rst.x = -rst.y;
02183 rst.y = rst.z;
02184 shift = 3.0;
02185 break;
02186 case 2:
02187 rst.x = rst.y;
02188 rst.y = rst.z;
02189 shift = 1.0;
02190 break;
02191 case 3:
02192 rst.y = rst.z;
02193 shift = 0.0;
02194 break;
02195 case 4:
02196 rst.x = -rst.x;
02197 rst.y = rst.z;
02198 shift = 2.0;
02199 break;
02200 case 5:
02201 rst.x = -rst.x;
02202 shift = 4.0;
02203 break;
02204 case 6:
02205 shift = 5.0;
02206 break;
02207 }
02208
02209
02210 rst.x = 0.5*rst.x + 0.5;
02211 rst.y = 0.5*rst.y + 0.5;
02212 rst.z = 0.0;
02213
02214 if( divided == m_texture_space)
02215 {
02216 rst.x = (shift + rst.x)/(m_bCapped ? 6.0 : 4.0);
02217 }
02218
02219 *T = m_uvw*rst;
02220
02221 return side0;
02222 }
02223
02224 int ON_TextureMapping::Evaluate(
02225 const ON_3dPoint& P,
02226 const ON_3dVector& N,
02227 ON_3dPoint* T,
02228 const ON_Xform& P_xform,
02229 const ON_Xform& N_xform
02230 ) const
02231 {
02232 int rc;
02233 ON_3dPoint Q = P*P_xform;
02234 if ( ON_TextureMapping::ray_projection == m_projection )
02235 {
02236
02237 ON_3dVector V = N_xform*N;
02238 V.Unitize();
02239 rc = Evaluate(Q,V,T);
02240 }
02241 else
02242 {
02243
02244 rc = Evaluate(Q,N,T);
02245 }
02246 return rc;
02247 }
02248
02249 int ON_TextureMapping::Evaluate(
02250 const ON_3dPoint& P,
02251 const ON_3dVector& N,
02252 ON_3dPoint* T
02253 ) const
02254 {
02255 int rc;
02256
02257 switch(m_type)
02258 {
02259 case srfp_mapping:
02260 *T = m_uvw * P;
02261 rc = 1;
02262 break;
02263 case sphere_mapping:
02264 rc = EvaluateSphereMapping(P,N,T);
02265 break;
02266 case cylinder_mapping:
02267 rc = EvaluateCylinderMapping(P,N,T);
02268 break;
02269 case box_mapping:
02270 rc = EvaluateBoxMapping(P,N,T);
02271 break;
02272
02273 case mesh_mapping_primitive:
02274 rc = 0;
02275 break;
02276
02277 case srf_mapping_primitive:
02278 rc = 0;
02279 break;
02280
02281 case brep_mapping_primitive:
02282 rc = 0;
02283 break;
02284
02285 default:
02286 rc = EvaluatePlaneMapping(P,N,T);
02287 break;
02288 }
02289 return rc;
02290 }
02291
02292 ON__UINT32 ON_TextureMapping::MappingCRC() const
02293 {
02294
02295 ON__UINT32 crc32 = 0x12345678;
02296 crc32 = ON_CRC32(crc32,sizeof(m_type),&m_type);
02297 if ( ON_TextureMapping::srfp_mapping != m_type )
02298 {
02299
02300
02301 crc32 = ON_CRC32(crc32,sizeof(m_projection), &m_projection);
02302 crc32 = ON_CRC32(crc32,sizeof(m_texture_space), &m_texture_space);
02303 crc32 = ON_CRC32(crc32,sizeof(m_bCapped), &m_bCapped);
02304 crc32 = ON_CRC32(crc32,sizeof(m_Pxyz), &m_Pxyz);
02305
02306
02307 if ( 0 != m_mapping_primitive )
02308 {
02309 switch( m_type )
02310 {
02311 case ON_TextureMapping::mesh_mapping_primitive:
02312 {
02313 const ON_Mesh* mesh = ON_Mesh::Cast(m_mapping_primitive);
02314 if ( 0 == mesh )
02315 break;
02316 crc32 = mesh->DataCRC(crc32);
02317 if ( mesh->HasTextureCoordinates() )
02318 {
02319
02320
02321
02322
02323
02324 const ON_2fPoint* tex = mesh->m_T.Array();
02325 crc32 = ON_CRC32(crc32,mesh->m_T.Count()*sizeof(tex[0]),tex);
02326 }
02327 }
02328 break;
02329
02330 case ON_TextureMapping::brep_mapping_primitive:
02331 {
02332 const ON_Brep* brep = ON_Brep::Cast(m_mapping_primitive);
02333 if ( 0 == brep )
02334 break;
02335 crc32 = brep->DataCRC(crc32);
02336
02337
02338
02339
02340
02341
02342
02343
02344 }
02345 break;
02346
02347 case ON_TextureMapping::srf_mapping_primitive:
02348 {
02349 const ON_Surface* surface = ON_Surface::Cast(m_mapping_primitive);
02350 if ( 0 == surface )
02351 break;
02352 crc32 = surface->DataCRC(crc32);
02353 }
02354 break;
02355
02356 case ON_TextureMapping::no_mapping:
02357 case ON_TextureMapping::srfp_mapping:
02358 case ON_TextureMapping::plane_mapping:
02359 case ON_TextureMapping::cylinder_mapping:
02360 case ON_TextureMapping::sphere_mapping:
02361 case ON_TextureMapping::box_mapping:
02362 case ON_TextureMapping::force_32bit_mapping_projection:
02363 default:
02364 break;
02365 }
02366 }
02367
02368 }
02369
02370 crc32 = ON_CRC32(crc32,sizeof(m_uvw), &m_uvw);
02371 return crc32;
02372 }
02373
02374 bool ON_TextureMapping::RequiresVertexNormals() const
02375 {
02376 if ( ON_TextureMapping::srfp_mapping == m_type )
02377 return false;
02378
02379 if(m_projection == ray_projection)
02380 return true;
02381
02382 if(m_type == box_mapping)
02383 return true;
02384 if(m_type == cylinder_mapping && m_bCapped)
02385 return true;
02386
02387 return false;
02388 }
02389
02390 bool ON_TextureMapping::IsPeriodic(void) const
02391 {
02392 return (m_type == sphere_mapping || m_type == cylinder_mapping);
02393 }
02394
02395 bool ON_TextureMapping::HasMatchingTextureCoordinates(
02396 const ON_Mesh& mesh,
02397 const ON_Xform* mesh_xform
02398 ) const
02399 {
02400 bool rc = (mesh.HasTextureCoordinates())
02401 ? HasMatchingTextureCoordinates(mesh.m_Ttag,mesh_xform)
02402 : false;
02403
02404 return rc;
02405 }
02406
02407 bool ON_TextureMapping::HasMatchingTextureCoordinates(
02408 const ON_MappingTag& tag,
02409 const ON_Xform* mesh_xform
02410 ) const
02411 {
02412 bool rc = false;
02413
02414
02415
02416
02417
02418 if ( tag.m_mapping_crc == MappingCRC() )
02419 {
02420 rc = true;
02421
02422
02423
02424
02425
02426
02427
02428 if ( ON_TextureMapping::srfp_mapping != m_type
02429 && mesh_xform
02430 && mesh_xform->IsValid()
02431 && !mesh_xform->IsZero()
02432 && !tag.m_mesh_xform.IsZero()
02433 )
02434 {
02435
02436 const double* a = &mesh_xform->m_xform[0][0];
02437 const double* b = &tag.m_mesh_xform.m_xform[0][0];
02438 for ( int i = 16; i--; )
02439 {
02440 if ( fabs(*a++ - *b++) > ON_SQRT_EPSILON )
02441 {
02442 rc = false;
02443 break;
02444 }
02445 }
02446 }
02447 }
02448
02449 return rc;
02450 }
02451
02452 static
02453 bool GetSPTCHelper(
02454 const ON_Mesh& mesh,
02455 const ON_TextureMapping& mapping,
02456 float* tc,
02457 int tc_stride
02458 )
02459 {
02460 const int vcnt = mesh.m_V.Count();
02461 if ( vcnt <= 0 )
02462 return false;
02463 if ( !mesh.HasSurfaceParameters() )
02464 return false;
02465 const ON_2dPoint* S = mesh.m_S.Array();
02466 if ( !S )
02467 return false;
02468
02469 int i;
02470 double u, v, a, b;
02471
02472
02473
02474 ON_Interval srf_udom = mesh.m_srf_domain[0];
02475 ON_Interval srf_vdom = mesh.m_srf_domain[1];
02476 if ( !srf_udom.IsIncreasing() || !srf_vdom.IsIncreasing() )
02477 {
02478
02479 srf_udom.m_t[0] = srf_udom.m_t[1] = S[0].x;
02480 srf_vdom.m_t[0] = srf_vdom.m_t[1] = S[0].y;
02481 for ( i = 1; i < vcnt; i++ )
02482 {
02483 u = S[i].x;
02484 if (u < srf_udom.m_t[0]) srf_udom.m_t[0] = u;
02485 else if (u > srf_udom.m_t[1]) srf_udom.m_t[1] = u;
02486 v = S[i].y;
02487 if (v < srf_vdom.m_t[0]) srf_vdom.m_t[0] = v;
02488 else if (v > srf_vdom.m_t[1]) srf_vdom.m_t[1] = v;
02489 }
02490 if ( !srf_udom.IsIncreasing()
02491 || !srf_vdom.IsIncreasing() )
02492 {
02493 return false;
02494 }
02495 }
02496
02497 bool bHaveUVWXform = mapping.m_uvw.IsValid()
02498 && !mapping.m_uvw.IsIdentity()
02499 && !mapping.m_uvw.IsZero();
02500
02501 if ( mesh.HasPackedTextureRegion() )
02502 {
02503
02504
02505
02506 const ON_Interval tex_udom = mesh.m_packed_tex_domain[0];
02507 const ON_Interval tex_vdom = mesh.m_packed_tex_domain[1];
02508 for ( i = 0; i < vcnt; i++)
02509 {
02510
02511
02512
02513
02514 if (bHaveUVWXform)
02515 {
02516 const ON_2dPoint si = mapping.m_uvw*S[i];
02517 u = si.x;
02518 v = si.y;
02519 }
02520 else
02521 {
02522 u = S[i].x;
02523 v = S[i].y;
02524 }
02525
02526
02527 if ( mesh.m_packed_tex_rotate )
02528 {
02529
02530 a = 1.0 - srf_vdom.NormalizedParameterAt( v );
02531 b = srf_udom.NormalizedParameterAt( u );
02532 }
02533 else
02534 {
02535 a = srf_udom.NormalizedParameterAt( u );
02536 b = srf_vdom.NormalizedParameterAt( v );
02537 }
02538
02539
02540
02541 u = tex_udom.ParameterAt(a);
02542 v = tex_vdom.ParameterAt(b);
02543
02544 tc[0] = (float)u;
02545 tc[1] = (float)v;
02546 tc += tc_stride;
02547 }
02548 }
02549 else if ( bHaveUVWXform )
02550 {
02551 const ON_Xform xform(mapping.m_uvw);
02552 ON_3dPoint P;
02553 for ( i = 0; i < vcnt; i++)
02554 {
02555
02556 P.x = srf_udom.NormalizedParameterAt( S[i].x );
02557 P.y = srf_vdom.NormalizedParameterAt( S[i].y );
02558 P.z = 0.0;
02559
02560
02561 P = xform*P;
02562
02563 tc[0] = (float)P.x;
02564 tc[1] = (float)P.y;
02565 tc += tc_stride;
02566 }
02567 }
02568 else
02569 {
02570
02571
02572 for ( i = 0; i < vcnt; i++)
02573 {
02574
02575 a = srf_udom.NormalizedParameterAt( S[i].x );
02576 b = srf_vdom.NormalizedParameterAt( S[i].y );
02577
02578 tc[0] = (float)a;
02579 tc[1] = (float)b;
02580 tc += tc_stride;
02581 }
02582 }
02583
02584 return true;
02585 }
02586
02587
02588 bool ON_TextureMapping::GetTextureCoordinates(
02589 const ON_Mesh& mesh,
02590 ON_SimpleArray<ON_3fPoint>& T,
02591 const ON_Xform* mesh_xform,
02592 bool bLazy,
02593 ON_SimpleArray<int>* Tside
02594 ) const
02595 {
02596 if ( Tside )
02597 Tside->SetCount(0);
02598
02599 int i;
02600 const int vcnt = mesh.m_V.Count();
02601 if ( vcnt <= 0 )
02602 return false;
02603
02604 if ( bLazy )
02605 {
02606 int tci, tccount = mesh.m_TC.Count();
02607 for ( tci = 0; tci < tccount; tci++ )
02608 {
02609 if ( vcnt == mesh.m_TC[tci].m_T.Count() )
02610 {
02611 if ( HasMatchingTextureCoordinates(mesh.m_TC[tci].m_tag,mesh_xform) )
02612 {
02613 T = mesh.m_TC[tci].m_T;
02614 return true;
02615 }
02616 }
02617 }
02618
02619 if ( HasMatchingTextureCoordinates(mesh,mesh_xform ) )
02620 {
02621 T.Reserve(vcnt);
02622 T.SetCount(vcnt);
02623 const ON_2fPoint* f = mesh.m_T.Array();
02624 ON_3fPoint* d = T.Array();
02625 for ( i = vcnt; i--; f++, d++ )
02626 {
02627 d->x = f->x;
02628 d->y = f->y;
02629 d->z = 0.0f;
02630 }
02631 return true;
02632 }
02633 }
02634
02635 bool rc = false;
02636
02637 if ( ON_TextureMapping::srfp_mapping == m_type )
02638 {
02639
02640 T.Reserve(vcnt);
02641 T.SetCount(vcnt);
02642 T.Zero();
02643 rc = GetSPTCHelper(mesh,*this,&T[0].x,3);
02644 }
02645 else
02646 {
02647 ON_3dPoint P, tc;
02648 ON_3dVector N(0.0,0.0,0.0);
02649
02650 const ON_3fPoint* mesh_V = mesh.m_V.Array();
02651 const ON_3fVector* mesh_N = mesh.HasVertexNormals()
02652 ? mesh.m_N.Array()
02653 : 0;
02654
02655 T.Reserve(vcnt);
02656 T.SetCount(vcnt);
02657
02658 int* Tsd = 0;
02659 if ( Tside )
02660 {
02661 Tside->Reserve(vcnt);
02662 Tside->SetCount(vcnt);
02663 Tsd = Tside->Array();
02664 memset(Tsd,0,vcnt*sizeof(Tsd[0]));
02665 }
02666
02667 ON_Xform P_xform(1.0), N_xform(1.0);
02668 const double* PT = 0;
02669 const double* NT = 0;
02670 if ( mesh_xform )
02671 {
02672 if ( mesh_xform->IsZero() || mesh_xform->IsIdentity() )
02673 {
02674
02675 mesh_xform = 0;
02676 }
02677 else if ( 0.0 != mesh_xform->GetMappingXforms(P_xform,N_xform) )
02678 {
02679 PT = &P_xform[0][0];
02680 NT = &N_xform[0][0];
02681 }
02682 else
02683 {
02684 mesh_xform = 0;
02685 }
02686 }
02687
02688 const float* f;
02689 double w;
02690 int sd;
02691
02692 if (clspt_projection == m_projection && ON_TextureMapping::mesh_mapping_primitive == m_type && NULL != m_mapping_primitive)
02693 {
02694 rc = false;
02695 }
02696 else if ( mesh_N &&
02697 ( ray_projection == m_projection
02698 || ON_TextureMapping::box_mapping == m_type
02699 || ON_TextureMapping::cylinder_mapping == m_type
02700 || ON_TextureMapping::mesh_mapping_primitive == m_type
02701 )
02702 )
02703 {
02704
02705 if ( PT && NT )
02706 {
02707
02708
02709 for (i = 0; i < vcnt; i++)
02710 {
02711 f = &mesh_V[i].x;
02712 w = PT[12]*f[0] + PT[13]*f[1] + PT[14]*f[2] + PT[15];
02713 w = (0.0 != w) ? 1.0/w : 1.0;
02714 P.x = w*(PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2] + PT[ 3]);
02715 P.y = w*(PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2] + PT[ 7]);
02716 P.z = w*(PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2] + PT[11]);
02717
02718 f = &mesh_N[i].x;
02719 N.x = PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2];
02720 N.y = PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2];
02721 N.z = PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2];
02722 N.Unitize();
02723 sd = Evaluate(P,N,&tc);
02724 T[i] = tc;
02725 if ( Tsd ) Tsd[i] = sd;
02726 }
02727 }
02728 else
02729 {
02730
02731 for (i = 0; i < vcnt; i++)
02732 {
02733 P = mesh_V[i];
02734 N = mesh_N[i];
02735 sd = Evaluate(P,N,&tc);
02736 T[i] = tc;
02737 if ( Tsd ) Tsd[i] = sd;
02738 }
02739 }
02740 }
02741 else if ( PT )
02742 {
02743
02744
02745 for ( i = 0; i < vcnt; i++ )
02746 {
02747 f = &mesh_V[i].x;
02748 w = PT[12]*f[0] + PT[13]*f[1] + PT[14]*f[2] + PT[15];
02749 w = (0.0 != w) ? 1.0/w : 1.0;
02750 P.x = w*(PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2] + PT[ 3]);
02751 P.y = w*(PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2] + PT[ 7]);
02752 P.z = w*(PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2] + PT[11]);
02753 sd = Evaluate(P,N,&tc);
02754 T[i] = tc;
02755 if ( Tsd )
02756 Tsd[i] = sd;
02757 }
02758 }
02759 else
02760 {
02761
02762 for ( i = 0; i < vcnt; i++ )
02763 {
02764 P = mesh_V[i];
02765 sd = Evaluate(P,N,&tc);
02766 T[i] = tc;
02767 if ( Tsd )
02768 Tsd[i] = sd;
02769 }
02770 }
02771 rc = true;
02772 }
02773
02774 return rc;
02775 }
02776
02777 static
02778 void ThreeToTwoHelper(
02779 const ON_SimpleArray<ON_3fPoint>& T3,
02780 ON_SimpleArray<ON_2fPoint>& T2
02781 )
02782 {
02783 int i = T3.Count();
02784 const ON_3fPoint* t3 = T3.Array();
02785
02786 T2.Reserve(i);
02787 T2.SetCount(i);
02788 ON_2fPoint* t2 = T2.Array();
02789 while(i--)
02790 {
02791 t2->x = t3->x;
02792 t2->y = t3->y;
02793 t2++;
02794 t3++;
02795 }
02796 }
02797
02798 bool ON_TextureMapping::GetTextureCoordinates(
02799 const ON_Mesh& mesh,
02800 ON_SimpleArray<ON_2fPoint>& T,
02801 const ON_Xform* mesh_xform,
02802 bool bLazy,
02803 ON_SimpleArray<int>* Tside
02804 ) const
02805 {
02806 bool rc = false;
02807 if ( Tside )
02808 Tside->SetCount(0);
02809 if ( bLazy )
02810 {
02811 if ( HasMatchingTextureCoordinates(mesh,mesh_xform ) )
02812 {
02813 if ( T.Array() != mesh.m_T.Array() )
02814 {
02815
02816 T = mesh.m_T;
02817 }
02818 return true;
02819 }
02820 else
02821 {
02822 int vcnt = mesh.m_V.Count();
02823 int tci, tccount = mesh.m_TC.Count();
02824 for ( tci = 0; tci < tccount; tci++ )
02825 {
02826 if ( vcnt == mesh.m_TC[tci].m_T.Count() )
02827 {
02828 if ( HasMatchingTextureCoordinates(mesh.m_TC[tci].m_tag,mesh_xform) )
02829 {
02830
02831 ThreeToTwoHelper(mesh.m_TC[tci].m_T,T);
02832 return true;
02833 }
02834 }
02835 }
02836 }
02837 }
02838
02839 if ( ON_TextureMapping::srfp_mapping == m_type )
02840 {
02841
02842 T.Reserve(mesh.m_V.Count());
02843 T.SetCount(mesh.m_V.Count());
02844 T.Zero();
02845 rc = GetSPTCHelper(mesh,*this,&T[0].x,2);
02846 }
02847 else
02848 {
02849 T.SetCount(0);
02850 ON_SimpleArray<ON_3fPoint> T3;
02851 if ( GetTextureCoordinates(mesh, T3, mesh_xform, false, Tside ) )
02852 {
02853
02854 ThreeToTwoHelper(T3,T);
02855 rc = true;
02856 }
02857 }
02858 return rc;
02859 }
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903 class ON__CMeshFaceTC
02904 {
02905
02906
02907 public:
02908 int fi;
02909 int quad[4];
02910 float Tx[4];
02911 bool bSetT[4];
02912 };
02913
02914 class ON__CChangeTextureCoordinateHelper
02915 {
02916
02917
02918 public:
02919 ON__CChangeTextureCoordinateHelper( ON_Mesh& mesh, int newvcnt, float*& mesh_T );
02920 ~ON__CChangeTextureCoordinateHelper();
02921
02922 int DupVertex(int vi);
02923 void ChangeTextureCoordinate(int* Fvi, int fvi, float x, float y, float* mesh_T, int mesh_T_stride );
02924
02925 int m_tci;
02926
02927 ON_Mesh& m_mesh;
02928 ON_3dPointArray* m_mesh_dV;
02929 bool m_bHasVertexNormals;
02930 bool m_bHasVertexTextures;
02931 bool m_bHasVertexColors;
02932 bool m_bHasSurfaceParameters;
02933 bool m_bHasPrincipalCurvatures;
02934 bool m_bHasHiddenVertices;
02935
02936 bool m_bHasCachedTextures;
02937 ON_SimpleArray< ON_TextureCoordinates* > m_TC;
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947 int m_vuse_count;
02948 ON_SimpleArray< unsigned int > m_vuse;
02949 private:
02950
02951 ON__CChangeTextureCoordinateHelper(const ON__CChangeTextureCoordinateHelper&);
02952 ON__CChangeTextureCoordinateHelper& operator=(const ON__CChangeTextureCoordinateHelper&);
02953 };
02954
02955 void ON__CChangeTextureCoordinateHelper::ChangeTextureCoordinate(int* Fvi, int fvi, float x, float y,
02956 float* mesh_T, int mesh_T_stride )
02957 {
02958 int oldvi = Fvi[fvi];
02959 float* T = mesh_T+(oldvi*mesh_T_stride);
02960 if ( x != T[0] || (y != ON_UNSET_FLOAT && y != T[1]) )
02961 {
02962 int newvi = DupVertex(oldvi);
02963 T = mesh_T + (newvi*mesh_T_stride);
02964 T[0] = x;
02965 if ( y != ON_UNSET_FLOAT )
02966 T[1] = y;
02967
02968 if ( 2 == fvi && oldvi == Fvi[3] )
02969 {
02970 Fvi[2] = newvi;
02971 Fvi[3] = newvi;
02972 }
02973 else
02974 {
02975 Fvi[fvi] = newvi;
02976 }
02977 }
02978 }
02979
02980
02981 ON__CChangeTextureCoordinateHelper::ON__CChangeTextureCoordinateHelper(
02982 ON_Mesh& mesh,
02983 int newvcnt,
02984 float*& mesh_T )
02985 : m_mesh(mesh)
02986 , m_mesh_dV(0)
02987 , m_vuse_count(0)
02988 {
02989
02990 m_mesh.DestroyTopology();
02991 m_mesh.DestroyPartition();
02992 m_mesh.DestroyTree();
02993
02994 m_tci = -1;
02995
02996 const int vcnt = m_mesh.m_V.Count();
02997
02998
02999
03000
03001
03002
03003
03004 m_mesh.m_V.Reserve(vcnt+newvcnt);
03005
03006 if ( m_mesh.HasDoublePrecisionVertices()
03007 && m_mesh.DoublePrecisionVerticesAreValid()
03008 )
03009 {
03010 m_mesh_dV = &m_mesh.DoublePrecisionVertices();
03011 m_mesh_dV->Reserve(vcnt+newvcnt);
03012 }
03013 else
03014 {
03015 m_mesh.DestroyDoublePrecisionVertices();
03016 }
03017
03018 m_bHasVertexNormals = m_mesh.HasVertexNormals();
03019 if ( m_bHasVertexNormals )
03020 m_mesh.m_N.Reserve(vcnt+newvcnt);
03021
03022 m_bHasVertexTextures = m_mesh.HasTextureCoordinates();
03023 if ( m_bHasVertexTextures )
03024 {
03025 float* p = (float*)m_mesh.m_T.Array();
03026 m_mesh.m_T.Reserve(vcnt+newvcnt);
03027 if ( p == mesh_T )
03028 mesh_T = (float*)m_mesh.m_T.Array();
03029 }
03030
03031 m_bHasVertexColors = m_mesh.HasVertexColors();
03032 if ( m_bHasVertexColors )
03033 m_mesh.m_C.Reserve(vcnt+newvcnt);
03034
03035 m_bHasSurfaceParameters = m_mesh.HasSurfaceParameters();
03036 if ( m_bHasSurfaceParameters )
03037 m_mesh.m_S.Reserve(vcnt+newvcnt);
03038
03039 m_bHasPrincipalCurvatures = m_mesh.HasPrincipalCurvatures();
03040 if ( m_bHasPrincipalCurvatures )
03041 m_mesh.m_K.Reserve(vcnt+newvcnt);
03042
03043 m_bHasHiddenVertices = (0 != m_mesh.HiddenVertexArray());
03044 if ( m_bHasHiddenVertices )
03045 m_mesh.m_H.Reserve(vcnt+newvcnt);
03046
03047
03048
03049 m_bHasCachedTextures = false;
03050 int tci, tccount = m_mesh.m_TC.Count();
03051 m_TC.Reserve(tccount);
03052 for ( tci = 0; tci < tccount; tci++ )
03053 {
03054 ON_TextureCoordinates& tc = m_mesh.m_TC[tci];
03055 if ( vcnt == tc.m_T.Count() )
03056 {
03057 m_bHasCachedTextures = true;
03058 float* p = (float*)tc.m_T.Array();
03059 tc.m_T.Reserve(vcnt+newvcnt);
03060 if ( p == mesh_T )
03061 mesh_T = (float*)tc.m_T.Array();
03062 m_TC.Append( &tc );
03063 }
03064 }
03065 }
03066
03067
03068 ON__CChangeTextureCoordinateHelper::~ON__CChangeTextureCoordinateHelper()
03069 {
03070 if ( 0 != m_mesh_dV )
03071 {
03072 m_mesh.SetDoublePrecisionVerticesAsValid();
03073 m_mesh.SetSinglePrecisionVerticesAsValid();
03074 m_mesh_dV = 0;
03075 }
03076 }
03077
03078 int ON__CChangeTextureCoordinateHelper::DupVertex(int vi)
03079 {
03080 if ( 0 == m_vuse_count )
03081 {
03082
03083
03084
03085
03086
03087
03088
03089
03090 m_vuse_count = m_mesh.m_V.Count();
03091 m_vuse.Reserve(m_vuse_count);
03092 m_vuse.SetCount(m_vuse_count);
03093 m_vuse.Zero();
03094 for ( int fi = 0; fi < m_mesh.m_F.Count(); fi++ )
03095 {
03096 const int* Fvi = m_mesh.m_F[fi].vi;
03097 int i = Fvi[0];
03098 if ( i >= 0 && i < m_vuse_count )
03099 m_vuse[i]++;
03100 i = Fvi[1];
03101 if ( i >= 0 && i < m_vuse_count )
03102 m_vuse[i]++;
03103 i = Fvi[2];
03104 if ( i >= 0 && i < m_vuse_count )
03105 m_vuse[i]++;
03106 i = Fvi[3];
03107 if ( Fvi[2] != i && i >= 0 && i < m_vuse_count )
03108 m_vuse[i]++;
03109 }
03110 }
03111
03112 if ( vi >= 0 && vi < m_vuse_count )
03113 {
03114 if ( m_vuse[vi] <= 1 )
03115 return vi;
03116
03117
03118 m_vuse[vi]--;
03119 }
03120
03121
03122 m_mesh.m_V.AppendNew();
03123 *m_mesh.m_V.Last() = m_mesh.m_V[vi];
03124 if ( 0 != m_mesh_dV )
03125 {
03126 m_mesh_dV->AppendNew();
03127 *(m_mesh_dV->Last()) = m_mesh_dV->operator[](vi);
03128 }
03129 if ( m_bHasVertexTextures )
03130 {
03131 m_mesh.m_T.AppendNew();
03132 *m_mesh.m_T.Last() = m_mesh.m_T[vi];
03133 }
03134 if ( m_bHasVertexNormals )
03135 {
03136 m_mesh.m_N.AppendNew();
03137 *m_mesh.m_N.Last() = m_mesh.m_N[vi];
03138 }
03139 if ( m_bHasVertexColors )
03140 {
03141 m_mesh.m_C.AppendNew();
03142 *m_mesh.m_C.Last() = m_mesh.m_C[vi];
03143 }
03144 if ( m_bHasSurfaceParameters )
03145 {
03146 m_mesh.m_S.AppendNew();
03147 *m_mesh.m_S.Last() = m_mesh.m_S[vi];
03148 }
03149 if ( m_bHasPrincipalCurvatures )
03150 {
03151 m_mesh.m_K.AppendNew();
03152 *m_mesh.m_K.Last() = m_mesh.m_K[vi];
03153 }
03154 if ( m_bHasHiddenVertices )
03155 {
03156 m_mesh.m_H.AppendNew();
03157 if ( 0 != (*m_mesh.m_H.Last() = m_mesh.m_H[vi]) )
03158 m_mesh.m_hidden_count++;
03159 }
03160
03161 if ( m_bHasCachedTextures )
03162 {
03163
03164
03165
03166
03167
03168
03169 int tccount = m_TC.Count();
03170 for ( int i = 0; i < tccount; i++ )
03171 {
03172 ON_SimpleArray<ON_3fPoint>& T = m_TC[i]->m_T;
03173 T.AppendNew();
03174 *T.Last() = T[vi];
03175 }
03176 }
03177
03178 return m_mesh.m_V.Count()-1;
03179 }
03180
03181
03182 static
03183 float PoleFix( float t0, float t1 )
03184 {
03185 float t = ( ON_UNSET_FLOAT == t0 )
03186 ? t1
03187 : ((ON_UNSET_FLOAT == t1 ) ? t0 : (0.5f*(t0+t1)));
03188 return t;
03189 }
03190
03191 static
03192 int IntersectBoxSideRayHelper(int side, const ON_3dPoint& rst, const ON_3dVector& n, double* s)
03193 {
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204 double nx;
03205 ON_3dPoint Q;
03206 double t,t0,t1;
03207 int dir;
03208
03209
03210 switch(side)
03211 {
03212 case 1:
03213 t1 = -1.0;
03214 dir = 0;
03215 break;
03216 case 2:
03217 t1 = 1.0;
03218 dir = 0;
03219 break;
03220 case 3:
03221 t1 = -1.0;
03222 dir = 1;
03223 break;
03224 case 4:
03225 t1 = 1.0;
03226 dir = 1;
03227 break;
03228 case 5:
03229 t1 = -1.0;
03230 dir = 2;
03231 break;
03232 case 6:
03233 t1 = 1.0;
03234 dir = 2;
03235 break;
03236 default:
03237 *s = ON_UNSET_VALUE;
03238 return 0;
03239 break;
03240 }
03241
03242
03243 nx = (&n.x)[dir];
03244 t0 = (t1 - (&rst.x)[dir]);
03245 if ( fabs(t0) >= fabs(nx)*on__overflow_tol )
03246 {
03247 *s = ON_UNSET_VALUE;
03248 return 0;
03249 }
03250
03251 t0 /= nx;
03252 Q = rst + t0*n;
03253 if ( dir )
03254 {
03255 t = Q.x;
03256 Q.x = Q[dir];
03257 Q[dir] = t;
03258 }
03259 if ( fabs(Q.x-t1) > ON_SQRT_EPSILON || fabs(Q.y) > 1.0e8 || fabs(Q.z) > 1.0e8 )
03260 {
03261 *s = ON_UNSET_VALUE;
03262 return 0;
03263 }
03264
03265
03266 *s = t0;
03267 return side;
03268 }
03269
03270 static
03271 bool EvBoxSideTextureCoordinateHelper2(
03272 int side,
03273 const ON_TextureMapping& box_mapping,
03274 const ON_3dPoint& P,
03275 const ON_3dVector& N,
03276 ON_3dPoint* T
03277 )
03278 {
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290
03291 ON_3dPoint rst(box_mapping.m_Pxyz*P);
03292
03293 ON_3dVector n(box_mapping.m_Nxyz*N);
03294 n.Unitize();
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304 if ( ON_TextureMapping::ray_projection == box_mapping.m_projection )
03305 {
03306 double s;
03307 if ( side == IntersectBoxSideRayHelper(side, rst, n, &s) )
03308 {
03309
03310 rst = rst + s*n;
03311 }
03312 }
03313
03314 double shift = 0.0;
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324 switch(side)
03325 {
03326 case 1:
03327 rst.x = -rst.y;
03328 rst.y = rst.z;
03329 shift = 3.0;
03330 break;
03331 case 2:
03332 rst.x = rst.y;
03333 rst.y = rst.z;
03334 shift = 1.0;
03335 break;
03336 case 3:
03337 rst.y = rst.z;
03338 shift = 0.0;
03339 break;
03340 case 4:
03341 rst.x = -rst.x;
03342 rst.y = rst.z;
03343 shift = 2.0;
03344 break;
03345 case 5:
03346 rst.x = -rst.x;
03347 shift = 4.0;
03348 break;
03349 case 6:
03350 shift = 5.0;
03351 break;
03352 default:
03353 return 0;
03354 break;
03355 }
03356
03357
03358 rst.x = 0.5*rst.x + 0.5;
03359 rst.y = 0.5*rst.y + 0.5;
03360 rst.z = 0.0;
03361
03362 if( ON_TextureMapping::divided == box_mapping.m_texture_space)
03363 {
03364 rst.x = (shift + rst.x)/(box_mapping.m_bCapped ? 6.0 : 4.0);
03365 }
03366
03367 *T = box_mapping.m_uvw*rst;
03368
03369 return true;
03370 }
03371
03372 static
03373 bool EvBoxSideTextureCoordinateHelper1(
03374 const ON_Mesh& mesh,
03375 const ON_Xform* mesh_xform,
03376 int vi,
03377 int side,
03378 const ON_TextureMapping& box_mapping,
03379 float* Tx,
03380 float* Ty
03381 )
03382 {
03383 bool rc = false;
03384 ON_3dPoint P, tc;
03385 ON_3dVector N(0.0,0.0,0.0);
03386
03387 const ON_3fPoint* mesh_V = mesh.m_V.Array();
03388 const ON_3fVector* mesh_N = mesh.HasVertexNormals()
03389 ? mesh.m_N.Array()
03390 : 0;
03391
03392 ON_Xform P_xform(1.0), N_xform(1.0);
03393 const double* PT = 0;
03394 const double* NT = 0;
03395 if ( mesh_xform )
03396 {
03397 if ( mesh_xform->IsZero() || mesh_xform->IsIdentity() )
03398 {
03399
03400 mesh_xform = 0;
03401 }
03402 else if ( 0.0 != mesh_xform->GetMappingXforms(P_xform,N_xform) )
03403 {
03404 PT = &P_xform[0][0];
03405 NT = &N_xform[0][0];
03406 }
03407 else
03408 {
03409 mesh_xform = 0;
03410 }
03411 }
03412
03413 const float* f;
03414 double w;
03415
03416 if ( mesh_N && ON_TextureMapping::ray_projection == box_mapping.m_projection )
03417 {
03418
03419 if ( PT && NT )
03420 {
03421
03422
03423 f = &mesh_V[vi].x;
03424 w = PT[12]*f[0] + PT[13]*f[1] + PT[14]*f[2] + PT[15];
03425 w = (0.0 != w) ? 1.0/w : 1.0;
03426 P.x = w*(PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2] + PT[ 3]);
03427 P.y = w*(PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2] + PT[ 7]);
03428 P.z = w*(PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2] + PT[11]);
03429
03430 f = &mesh_N[vi].x;
03431 N.x = PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2];
03432 N.y = PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2];
03433 N.z = PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2];
03434 N.Unitize();
03435 }
03436 else
03437 {
03438
03439 P = mesh_V[vi];
03440 N = mesh_N[vi];
03441 }
03442 }
03443 else if ( PT )
03444 {
03445
03446
03447 f = &mesh_V[vi].x;
03448 w = PT[12]*f[0] + PT[13]*f[1] + PT[14]*f[2] + PT[15];
03449 w = (0.0 != w) ? 1.0/w : 1.0;
03450 P.x = w*(PT[0]*f[0] + PT[1]*f[1] + PT[ 2]*f[2] + PT[ 3]);
03451 P.y = w*(PT[4]*f[0] + PT[5]*f[1] + PT[ 6]*f[2] + PT[ 7]);
03452 P.z = w*(PT[8]*f[0] + PT[9]*f[1] + PT[10]*f[2] + PT[11]);
03453 }
03454 else
03455 {
03456
03457 P = mesh_V[vi];
03458 }
03459
03460
03461 rc = EvBoxSideTextureCoordinateHelper2(side,box_mapping,P,N,&tc);
03462 if (rc)
03463 {
03464 rc = tc.IsValid();
03465 if (rc)
03466 {
03467 *Tx = (float)tc.x;
03468 *Ty = (float)tc.y;
03469 }
03470 }
03471 return rc;
03472 }
03473
03474
03475 class ON__CNewMeshFace
03476 {
03477 public:
03478 int fi;
03479 int newvcnt;
03480 bool bNewV[4];
03481 ON_2fPoint tc[4];
03482 };
03483
03484 static
03485 float TcDistanceHelper(const ON_2fPoint& tc)
03486 {
03487 float dx = (tc.x > 0.5f) ? (1.0f-tc.x) : tc.x;
03488 if ( dx < 0.0f)
03489 return 0.0f;
03490 float dy = (tc.y > 0.5f) ? (1.0f-tc.y) : tc.y;
03491 if ( dy < 0.0f)
03492 return 0.0f;
03493 return (dx < dy) ? dx : dy;
03494 }
03495
03496 static
03497 void AdjustSingleBoxTextureCoordinatesHelper(
03498 ON_Mesh& mesh,
03499 const ON_Xform* mesh_xform,
03500 float* mesh_T,
03501 int mesh_T_stride,
03502 const int* Tsd,
03503 const ON_TextureMapping& box_mapping
03504 )
03505 {
03506 const int vcnt = mesh.m_V.Count();
03507 const int fcnt = mesh.m_F.Count();
03508 if ( vcnt < 3 || fcnt < 1 || vcnt != mesh.m_T.Count() || !Tsd )
03509 return;
03510 const ON_MeshFace* mesh_F = mesh.m_F.Array();
03511 const int* Fvi;
03512 int j, k, fi, sd[4], fvicnt, side, newvcnt=0;
03513 ON__CNewMeshFace mf;
03514 ON_2fPoint tc;
03515 ON_SimpleArray<ON__CNewMeshFace> mflist(512);
03516 float d;
03517 for ( fi = 0; fi < fcnt; fi++ )
03518 {
03519 Fvi = mesh_F[fi].vi;
03520 sd[0] = Tsd[Fvi[0]];
03521 sd[1] = Tsd[Fvi[1]];
03522 sd[2] = Tsd[Fvi[2]];
03523 sd[3] = Tsd[Fvi[3]];
03524 if ( sd[0] == sd[1] && sd[0] == sd[2] && sd[0] == sd[3] )
03525 {
03526
03527 continue;
03528 }
03529 fvicnt = (Fvi[2] != Fvi[3]) ? 4 : 3;
03530
03531 memset(&mf,0,sizeof(mf));
03532 mf.tc[0] = mesh_T + (Fvi[0]*mesh_T_stride);
03533 mf.tc[1] = mesh_T + (Fvi[1]*mesh_T_stride);
03534 mf.tc[2] = mesh_T + (Fvi[2]*mesh_T_stride);
03535 mf.tc[3] = mesh_T + (Fvi[3]*mesh_T_stride);
03536
03537
03538 side = sd[0];
03539 d = TcDistanceHelper(mf.tc[0]);
03540 for ( j = 1; j < fvicnt; j++ )
03541 {
03542 float d1 = TcDistanceHelper(mf.tc[j]);
03543 if (d1 > d)
03544 {
03545 side = sd[j];
03546 d = d1;
03547 }
03548 }
03549
03550
03551
03552
03553
03554
03555
03556 for ( j = 0; j < fvicnt; j++ )
03557 {
03558 if ( sd[j] != side )
03559 {
03560
03561 if ( EvBoxSideTextureCoordinateHelper1(
03562 mesh,
03563 mesh_xform,
03564 Fvi[j],
03565 side,
03566 box_mapping,
03567 &tc.x,&tc.y) )
03568 {
03569 if ( tc.x != mf.tc[j].x || tc.y != mf.tc[j].y )
03570 {
03571 mf.tc[j] = tc;
03572 mf.bNewV[j] = true;
03573 mf.newvcnt++;
03574 }
03575 }
03576 else
03577 break;
03578 }
03579 }
03580 if ( j >= fvicnt && mf.newvcnt > 0 )
03581 {
03582 mf.fi = fi;
03583 newvcnt += mf.newvcnt;
03584 mflist.Append(mf);
03585 }
03586 }
03587
03588 if ( newvcnt <= 0 )
03589 return;
03590
03591 ON__CChangeTextureCoordinateHelper helper(mesh,vcnt+newvcnt,mesh_T);
03592
03593 const int mflist_count = mflist.Count();
03594
03595 for ( k = 0; k < mflist_count; k++ )
03596 {
03597 mf = mflist[k];
03598 int* fvi = mesh.m_F[mf.fi].vi;
03599 fvicnt = (fvi[2]!=fvi[3]) ? 4 : 3;
03600 for ( j = 0; j < fvicnt; j++ )
03601 {
03602 if ( mf.bNewV[j] )
03603 {
03604 helper.ChangeTextureCoordinate(fvi,j,mf.tc[j].x,mf.tc[j].y,mesh_T,mesh_T_stride);
03605 }
03606 }
03607 }
03608 }
03609
03610 static
03611 void AdjustMeshPeriodicTextureCoordinatesHelper(
03612 ON_Mesh& mesh,
03613 const ON_Xform* mesh_xform,
03614 float* mesh_T,
03615 int mesh_T_stride,
03616 const int* Tsd,
03617 double two_pi_tc,
03618 const ON_TextureMapping& mapping
03619 )
03620 {
03621
03622
03623
03624
03625
03626 const int vcnt = mesh.m_V.Count();
03627 const int fcnt = mesh.m_F.Count();
03628 if ( vcnt < 3 || fcnt < 1 || vcnt != mesh.m_T.Count() )
03629 return;
03630
03631
03632 const ON_TextureMapping::TYPE mapping_type = mapping.m_type;
03633 const bool bSphereCheck = ( ON_TextureMapping::sphere_mapping == mapping_type );
03634 const bool bCylinderCheck = (Tsd && ON_TextureMapping::cylinder_mapping == mapping_type);
03635 const bool bBoxCheck = (Tsd && ON_TextureMapping::box_mapping == mapping_type);
03636
03637 if ( bBoxCheck && ON_TextureMapping::single == mapping.m_texture_space )
03638 {
03639 AdjustSingleBoxTextureCoordinatesHelper( mesh, mesh_xform, mesh_T, mesh_T_stride, Tsd, mapping );
03640 return;
03641 }
03642
03643 ON_Workspace ws;
03644 int* quad = ws.GetIntMemory(vcnt);
03645 float* Tx = (float*)ws.GetMemory(vcnt*sizeof(Tx[0]));
03646 float t;
03647 int vi, ti, q=0;
03648 int ftc_count = 0;
03649
03650 const float ang0 = (float)(0.25*two_pi_tc);
03651 const float ang1 = (float)(0.75*two_pi_tc);
03652
03653
03654 for ( vi = ti = 0; vi < vcnt; vi++, ti += mesh_T_stride )
03655 {
03656 quad[vi] = 0;
03657 Tx[vi] = mesh_T[ti];
03658 if ( bCylinderCheck )
03659 {
03660 if ( 1 != Tsd[vi] )
03661 continue;
03662 }
03663 else if ( bBoxCheck )
03664 {
03665 if ( 1 != Tsd[vi] && 3 != Tsd[vi] )
03666 continue;
03667 }
03668 else if ( bSphereCheck )
03669 {
03670 t = mesh_T[ti+1];
03671 if ( t < 0.001f )
03672 {
03673 quad[vi] = 8; q |= 8;
03674 ftc_count++;
03675 continue;
03676 }
03677 if ( t > 0.999f )
03678 {
03679 quad[vi] = 8; q |= 8;
03680 ftc_count++;
03681 continue;
03682 }
03683 }
03684
03685 t = Tx[vi];
03686 if ( t < ang0 )
03687 {
03688 quad[vi] = 1; q |= 1;
03689 ftc_count++;
03690 }
03691 else if ( t > ang1 )
03692 {
03693 quad[vi] = 4; q |= 4;
03694 ftc_count++;
03695 }
03696 }
03697
03698 if ( 0 == q || 1 == q || 4 == q )
03699 {
03700
03701 return;
03702 }
03703
03704
03705
03706 ON_SimpleArray<ON__CMeshFaceTC> ftc_list(ftc_count*4 + 128);
03707 ftc_count = 0;
03708 const ON_MeshFace* F = mesh.m_F.Array();
03709 const int* Fvi;
03710 int fi;
03711 ON__CMeshFaceTC ftc;
03712 memset(&ftc,0,sizeof(ftc));
03713 float t0, t1;
03714
03715 for ( fi = 0; fi < fcnt; fi++ )
03716 {
03717 Fvi = F[fi].vi;
03718
03719 ftc.quad[0] = quad[Fvi[0]];
03720 ftc.quad[1] = quad[Fvi[1]];
03721 ftc.quad[2] = quad[Fvi[2]];
03722 ftc.quad[3] = quad[Fvi[3]];
03723
03724 q = (ftc.quad[0] | ftc.quad[1] | ftc.quad[2] | ftc.quad[3]);
03725 if ( 0 == q || 1 == q || 4 == q )
03726 {
03727
03728 continue;
03729 }
03730
03731
03732 ftc.fi = -1;
03733
03734 ftc.Tx[0] = Tx[Fvi[0]];
03735 ftc.Tx[1] = Tx[Fvi[1]];
03736 ftc.Tx[2] = Tx[Fvi[2]];
03737 ftc.Tx[3] = Tx[Fvi[3]];
03738
03739 if ( 0 != (8&q) )
03740 {
03741
03742 if ( 8 == ftc.quad[0] )
03743 {
03744 t0 = (8 == ftc.quad[3]) ? ON_UNSET_FLOAT : ftc.Tx[3];
03745 t1 = (8 == ftc.quad[1]) ? ON_UNSET_FLOAT : ftc.Tx[1];
03746 if ( ON_UNSET_FLOAT != t0 || ON_UNSET_FLOAT != t1 )
03747 {
03748 ftc.Tx[0] = PoleFix(t0,t1);
03749 ftc.quad[0] = ((ftc.Tx[0] < ang0) ? 1 : ((ftc.Tx[0] > ang1) ? 4 : 0));
03750 q |= ftc.quad[0];
03751 ftc.fi = fi;
03752 }
03753 }
03754 if ( 8 == ftc.quad[1] )
03755 {
03756 t0 = (8 == ftc.quad[0]) ? ON_UNSET_FLOAT : ftc.Tx[0];
03757 t1 = (8 == ftc.quad[2]) ? ON_UNSET_FLOAT : ftc.Tx[2];
03758 if ( ON_UNSET_FLOAT != t0 || ON_UNSET_FLOAT != t1 )
03759 {
03760 ftc.Tx[1] = PoleFix(t0,t1);
03761 ftc.quad[1] = ((ftc.Tx[1] < ang0) ? 1 : ((ftc.Tx[1] > ang1) ? 4 : 0));
03762 q |= ftc.quad[1];
03763 ftc.fi = fi;
03764 }
03765 }
03766 if ( 8 == ftc.quad[2] )
03767 {
03768 int k = (Fvi[2] == Fvi[3]) ? 0 : 3;
03769 t0 = (8 == ftc.quad[1]) ? ON_UNSET_FLOAT : ftc.Tx[1];
03770 t1 = (8 == ftc.quad[k]) ? ON_UNSET_FLOAT : ftc.Tx[k];
03771 if ( ON_UNSET_FLOAT != t0 || ON_UNSET_FLOAT != t1 )
03772 {
03773 ftc.Tx[2] = PoleFix(t0,t1);
03774 ftc.quad[2] = ((ftc.Tx[2] < ang0) ? 1 : ((ftc.Tx[2] > ang1) ? 4 : 0));
03775 if ( !k )
03776 {
03777 ftc.Tx[3] = ftc.Tx[2];
03778 ftc.quad[3] = ftc.quad[2];
03779 }
03780 q |= ftc.quad[2];
03781 ftc.fi = fi;
03782 }
03783 }
03784 if ( 8 == ftc.quad[3] && Fvi[2] != Fvi[3] )
03785 {
03786 t0 = (8 == ftc.quad[2]) ? ON_UNSET_FLOAT : ftc.Tx[2];
03787 t1 = (8 == ftc.quad[0]) ? ON_UNSET_FLOAT : ftc.Tx[0];
03788 if ( ON_UNSET_FLOAT != t0 || ON_UNSET_FLOAT != t1 )
03789 {
03790 ftc.Tx[3] = PoleFix(t0,t1);
03791 ftc.quad[3] = ((ftc.Tx[3] < ang0) ? 1 : ((ftc.Tx[3] > ang1) ? 4 : 0));
03792 q |= ftc.quad[3];
03793 ftc.fi = fi;
03794 }
03795 }
03796 }
03797
03798 if ( 5 == (5&q) )
03799 {
03800
03801 if ( two_pi_tc == 1.0 )
03802 {
03803 if ( 1 == ftc.quad[0] ) {ftc.Tx[0] += 1.0f; ftc.fi = fi;}
03804 if ( 1 == ftc.quad[1] ) {ftc.Tx[1] += 1.0f; ftc.fi = fi;}
03805 if ( 1 == ftc.quad[2] ) {ftc.Tx[2] += 1.0f; ftc.fi = fi;}
03806 if ( 1 == ftc.quad[3] ) {ftc.Tx[3] += 1.0f; ftc.fi = fi;}
03807 }
03808 else
03809 {
03810
03811
03812
03813
03814
03815
03816
03817 float f0=0.0f, f1=0.0f, twopitc = (float)two_pi_tc;;
03818
03819 if ( 1 == ftc.quad[0] ) f0 += ftc.Tx[0]; else if ( 4 == ftc.quad[0] ) f1 += twopitc-ftc.Tx[0];
03820 if ( 1 == ftc.quad[1] ) f0 += ftc.Tx[1]; else if ( 4 == ftc.quad[1] ) f1 += twopitc-ftc.Tx[1];
03821 if ( 1 == ftc.quad[2] ) f0 += ftc.Tx[2]; else if ( 4 == ftc.quad[2] ) f1 += twopitc-ftc.Tx[2];
03822 if (Fvi[2] != Fvi[3])
03823 {
03824 if ( 1 == ftc.quad[3] ) f0 += ftc.Tx[3]; else if ( 4 == ftc.quad[3] ) f1 += twopitc-ftc.Tx[3];
03825 }
03826 if (f0 >= f1 )
03827 {
03828
03829
03830 if ( 4 == ftc.quad[0] ) {ftc.Tx[0] = 0.0f; ftc.fi = fi;}
03831 if ( 4 == ftc.quad[1] ) {ftc.Tx[1] = 0.0f; ftc.fi = fi;}
03832 if ( 4 == ftc.quad[2] ) {ftc.Tx[2] = 0.0f; ftc.fi = fi;}
03833 if ( 4 == ftc.quad[3] ) {ftc.Tx[3] = 0.0f; ftc.fi = fi;}
03834 }
03835 else
03836 {
03837
03838
03839 if ( 1 == ftc.quad[0] ) {ftc.Tx[0] = twopitc; ftc.fi = fi;}
03840 if ( 1 == ftc.quad[1] ) {ftc.Tx[1] = twopitc; ftc.fi = fi;}
03841 if ( 1 == ftc.quad[2] ) {ftc.Tx[2] = twopitc; ftc.fi = fi;}
03842 if ( 1 == ftc.quad[3] ) {ftc.Tx[3] = twopitc; ftc.fi = fi;}
03843 }
03844 }
03845 }
03846
03847 if ( ftc.fi >= 0 )
03848 {
03849
03850 ftc_list.Append(ftc);
03851 }
03852 }
03853
03854 ftc_count = ftc_list.Count();
03855 if ( ftc_count <= 0 )
03856 return;
03857
03858
03859 int ftci;
03860 int newvcnt = 0;
03861 for ( ftci = 0; ftci < ftc_count; ftci++ )
03862 {
03863 ON__CMeshFaceTC& ftc = ftc_list[ftci];
03864 Fvi = F[ftc.fi].vi;
03865 if ( ftc.Tx[0] != Tx[Fvi[0]] )
03866 {
03867 ftc.bSetT[0] = true;
03868 newvcnt++;
03869 }
03870 if ( ftc.Tx[1] != Tx[Fvi[1]] )
03871 {
03872 ftc.bSetT[1] = true;
03873 newvcnt++;
03874 }
03875 if ( ftc.Tx[2] != Tx[Fvi[2]] )
03876 {
03877 ftc.bSetT[2] = true;
03878 newvcnt++;
03879 }
03880 if ( Fvi[2] != Fvi[3] )
03881 {
03882 if ( ftc.Tx[3] != Tx[Fvi[3]] )
03883 {
03884 ftc.bSetT[3] = true;
03885 newvcnt++;
03886 }
03887 }
03888 }
03889
03890 if ( newvcnt <= 0 )
03891 return;
03892
03893
03894 F = 0;
03895
03896
03897
03898 ON__CChangeTextureCoordinateHelper helper(mesh,newvcnt,mesh_T);
03899
03900
03901 for ( ftci = 0; ftci < ftc_count; ftci++ )
03902 {
03903 const ON__CMeshFaceTC& ftc = ftc_list[ftci];
03904 int* meshFvi = mesh.m_F[ftc.fi].vi;
03905
03906 if ( ftc.bSetT[0] )
03907 {
03908 helper.ChangeTextureCoordinate(meshFvi,0,ftc.Tx[0],ON_UNSET_FLOAT,mesh_T,mesh_T_stride);
03909 }
03910 if ( ftc.bSetT[1] )
03911 {
03912 helper.ChangeTextureCoordinate(meshFvi,1,ftc.Tx[1],ON_UNSET_FLOAT,mesh_T,mesh_T_stride);
03913 }
03914 if ( ftc.bSetT[2] )
03915 {
03916 helper.ChangeTextureCoordinate(meshFvi,2,ftc.Tx[2],ON_UNSET_FLOAT,mesh_T,mesh_T_stride);
03917 }
03918 if ( ftc.bSetT[3] )
03919 {
03920 helper.ChangeTextureCoordinate(meshFvi,3,ftc.Tx[3],ON_UNSET_FLOAT,mesh_T,mesh_T_stride);
03921 }
03922 }
03923 }
03924
03925 static
03926 bool SeamCheckHelper( const ON_TextureMapping& mp,
03927 double& two_pi_tc,
03928 ON_SimpleArray<int>& Tside,
03929 ON_SimpleArray<int>*& Tsd )
03930 {
03931 bool bSeamCheck = false;
03932 switch(mp.m_type)
03933 {
03934 case ON_TextureMapping::box_mapping:
03935 if ( ON_TextureMapping::divided == mp.m_texture_space )
03936 {
03937 if ( mp.m_bCapped )
03938 two_pi_tc = 2.0/3.0;
03939 Tsd = &Tside;
03940 bSeamCheck = true;
03941 }
03942 else if ( ON_TextureMapping::single == mp.m_texture_space )
03943 {
03944 Tsd = &Tside;
03945 bSeamCheck = true;
03946 }
03947 break;
03948
03949 case ON_TextureMapping::cylinder_mapping:
03950 if ( ON_TextureMapping::divided == mp.m_texture_space )
03951 {
03952 two_pi_tc = 2.0/3.0;
03953 Tsd = &Tside;
03954 }
03955 bSeamCheck = true;
03956 break;
03957
03958 case ON_TextureMapping::sphere_mapping:
03959 bSeamCheck = true;
03960 break;
03961
03962 default:
03963
03964 break;
03965 }
03966
03967 return bSeamCheck;
03968 }
03969
03970
03971 static inline bool HasSharedVertices(const ON_Mesh& mesh)
03972 {
03973 return mesh.m_V.Count() < ((mesh.TriangleCount() * 3) + (mesh.QuadCount() * 4));
03974 }
03975
03976
03977 const ON_TextureCoordinates* ON_Mesh::SetCachedTextureCoordinates(
03978 const class ON_TextureMapping& mapping,
03979 const class ON_Xform* mesh_xform,
03980 bool bLazy
03981 )
03982 {
03983 if ( mapping.RequiresVertexNormals() && !HasVertexNormals() )
03984 ComputeVertexNormals();
03985
03986 ON_TextureMapping mp = mapping;
03987 double two_pi_tc = 1.0;
03988 ON_SimpleArray<int> Tside;
03989 ON_SimpleArray<int>* Tsd = 0;
03990 bool bSeamCheck = SeamCheckHelper( mp, two_pi_tc, Tside, Tsd ) && HasSharedVertices(*this);
03991 if ( bSeamCheck )
03992 mp.m_uvw.Identity();
03993
03994 ON_TextureCoordinates* TC = 0;
03995 {
03996 for ( int i = 0; i < m_TC.Count(); i++ )
03997 {
03998 if ( m_TC[i].m_tag.m_mapping_id == mapping.m_mapping_id )
03999 {
04000 TC = &m_TC[i];
04001 break;
04002 }
04003 }
04004 }
04005 if ( bLazy && TC && mapping.HasMatchingTextureCoordinates( TC->m_tag, mesh_xform ) )
04006 return TC;
04007
04008 if ( !TC )
04009 {
04010 m_TC.AppendNew();
04011 TC = m_TC.Last();
04012 }
04013
04014
04015
04016 if ( !mp.GetTextureCoordinates( *this,TC->m_T,mesh_xform,false,Tsd) )
04017 {
04018 int tci = (int)(TC - m_TC.Array());
04019 m_TC.Remove(tci);
04020 return 0;
04021 }
04022
04023 TC->m_tag.Set(mapping);
04024 if ( mesh_xform && mesh_xform->IsValid()
04025 && !mesh_xform->IsIdentity()
04026 && !mesh_xform->IsZero()
04027 )
04028 {
04029 TC->m_tag.m_mesh_xform = *mesh_xform;
04030 }
04031
04032 TC->m_dim = 2;
04033
04034 if ( bSeamCheck && m_F.Count() > 0 && TC->m_T.Count() == m_V.Count() )
04035 {
04036 float* mesh_T = (float*)TC->m_T.Array();
04037 int mesh_T_stride = sizeof(TC->m_T[0])/sizeof(mesh_T[0]);
04038 if ( Tsd && Tside.Count() != m_V.Count() )
04039 Tsd = 0;
04040 AdjustMeshPeriodicTextureCoordinatesHelper( *this, mesh_xform, mesh_T, mesh_T_stride, Tsd ? Tside.Array() : 0, two_pi_tc, mp );
04041 mesh_T = 0;
04042 if ( !mapping.m_uvw.IsIdentity() && !mapping.m_uvw.IsZero() )
04043 {
04044
04045
04046 ON_3dPoint T;
04047 int vi, vcnt = TC->m_T.Count();
04048 ON_3fPoint* meshT = TC->m_T.Array();
04049 for ( vi = 0; vi < vcnt; vi++ )
04050 {
04051 T = meshT[vi];
04052 T = mapping.m_uvw*T;
04053 meshT[vi] = T;
04054 }
04055 }
04056 }
04057
04058 return TC;
04059 }
04060
04061 bool ON_Mesh::SetTextureCoordinates(
04062 const class ON_TextureMapping& mapping,
04063 const class ON_Xform* mesh_xform,
04064 bool bLazy
04065 )
04066 {
04067 if ( mapping.RequiresVertexNormals() && !HasVertexNormals() )
04068 ComputeVertexNormals();
04069
04070 InvalidateTextureCoordinateBoundingBox();
04071
04072 ON_SimpleArray<int> Tside;
04073 ON_SimpleArray<int>* Tsd = 0;
04074 ON_TextureMapping mp = mapping;
04075
04076 double two_pi_tc = 1.0;
04077
04078 bool bSeamCheck = SeamCheckHelper( mp, two_pi_tc, Tside, Tsd ) && HasSharedVertices(*this);
04079 if ( bSeamCheck )
04080 mp.m_uvw.Identity();
04081
04082
04083
04084 bool rc = mp.GetTextureCoordinates(*this,m_T,mesh_xform,bLazy,Tsd);
04085
04086 if (rc)
04087 {
04088
04089 m_Ttag.Set(mapping);
04090 if ( mesh_xform
04091 && mesh_xform->IsValid()
04092 && !mesh_xform->IsIdentity()
04093 && !mesh_xform->IsZero()
04094 )
04095 {
04096 m_Ttag.m_mesh_xform = *mesh_xform;
04097 }
04098 }
04099
04100 if ( rc && bSeamCheck && HasTextureCoordinates() && m_F.Count() > 0 )
04101 {
04102 float* mesh_T = (float*)m_T.Array();
04103 int mesh_T_stride = sizeof(m_T[0])/sizeof(mesh_T[0]);
04104 if ( Tsd && Tside.Count() != m_V.Count() )
04105 Tsd = 0;
04106 AdjustMeshPeriodicTextureCoordinatesHelper( *this, mesh_xform, mesh_T, mesh_T_stride, Tsd ? Tside.Array() : 0, two_pi_tc, mp );
04107 mesh_T = 0;
04108 if ( !mapping.m_uvw.IsIdentity() && !mapping.m_uvw.IsZero() )
04109 {
04110
04111
04112 ON_2fPoint* meshT = m_T.Array();
04113 ON_3dPoint T;
04114 int vi, vcnt = m_T.Count();
04115 for ( vi = 0; vi < vcnt; vi++ )
04116 {
04117 T.x = meshT[vi].x;
04118 T.y = meshT[vi].y;
04119 T.z = 0.0;
04120 T = mapping.m_uvw*T;
04121 meshT[vi].x = (float)T.x;
04122 meshT[vi].y = (float)T.y;
04123 }
04124 }
04125 }
04126
04127 return rc;
04128 }
04129
04130 ON_MappingChannel::ON_MappingChannel()
04131 {
04132 Default();
04133 }
04134
04135 void ON_MappingChannel::Default()
04136 {
04137 memset(this,0,sizeof(*this));
04138 m_mapping_channel_id = 1;
04139 m_mapping_index = -1;
04140 m_object_xform.Identity();
04141 }
04142
04143 int ON_MappingChannel::Compare( const ON_MappingChannel& other ) const
04144 {
04145 int rc = m_mapping_channel_id - other.m_mapping_channel_id;
04146 if (!rc)
04147 rc = ON_UuidCompare(m_mapping_id,other.m_mapping_id);
04148 return rc;
04149 }
04150
04151 bool ON_MappingChannel::Write( ON_BinaryArchive& archive ) const
04152 {
04153 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
04154 if (rc)
04155 {
04156 rc = archive.WriteInt(m_mapping_channel_id);
04157 if (rc) rc = archive.WriteUuid(m_mapping_id);
04158
04159
04160 if (rc) rc = archive.WriteXform(m_object_xform);
04161
04162 if ( !archive.EndWrite3dmChunk() )
04163 rc = false;
04164 }
04165 return rc;
04166 }
04167
04168 bool ON_MappingChannel::Read( ON_BinaryArchive& archive )
04169 {
04170 Default();
04171 int major_version = 0;
04172 int minor_version = 0;
04173 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
04174 if (rc)
04175 {
04176 rc = (1 == major_version);
04177 if (rc) rc = archive.ReadInt(&m_mapping_channel_id);
04178 if (rc) rc = archive.ReadUuid(m_mapping_id);
04179
04180 if ( rc && minor_version >= 1 )
04181 {
04182
04183 if (rc) rc = archive.ReadXform(m_object_xform);
04184 if (rc
04185 && archive.ArchiveOpenNURBSVersion() < 200610030
04186 && m_object_xform.IsZero()
04187 )
04188 {
04189
04190
04191
04192
04193
04194 m_object_xform.Identity();
04195 }
04196 }
04197
04198 if ( !archive.EndRead3dmChunk() )
04199 rc = false;
04200 }
04201 return rc;
04202 }
04203
04204
04205 ON_MaterialRef::ON_MaterialRef()
04206 {
04207 Default();
04208 }
04209
04210 ON_MappingRef::ON_MappingRef()
04211 {
04212 Default();
04213 }
04214
04215 void ON_MaterialRef::Default()
04216 {
04217 memset(this,0,sizeof(*this));
04218
04219 m_material_index = -1;
04220 m_material_backface_index = -1;
04221 m_material_source = ON::material_from_layer;
04222 }
04223
04224 void ON_MappingRef::Default()
04225 {
04226 m_plugin_id = ON_nil_uuid;
04227 m_mapping_channels.Destroy();
04228 }
04229
04230 int ON_MaterialRef::Compare( const ON_MaterialRef& other ) const
04231 {
04232 int rc = ON_UuidCompare(m_plugin_id,other.m_plugin_id);
04233 if (rc)
04234 rc = ((int)m_material_source) - ((int)other.m_material_source);
04235 if (!rc)
04236 rc = ON_UuidCompare(m_material_id,other.m_material_id);
04237 if (!rc)
04238 rc = ON_UuidCompare(m_material_backface_id,other.m_material_backface_id);
04239 return rc;
04240 }
04241
04242 int ON_MappingRef::Compare( const ON_MappingRef& other ) const
04243 {
04244 int rc = ON_UuidCompare(m_plugin_id,other.m_plugin_id);
04245 if ( !rc)
04246 {
04247 const int count = m_mapping_channels.Count();
04248 rc = count - other.m_mapping_channels.Count();
04249 if (!rc)
04250 {
04251 for ( int i = 0; i < count && !rc; i++ )
04252 {
04253 rc = m_mapping_channels[i].Compare(other.m_mapping_channels[i]);
04254 }
04255 }
04256 }
04257 return rc;
04258 }
04259
04260
04261 bool ON_MaterialRef::Write( ON_BinaryArchive& archive ) const
04262 {
04263 bool rc = archive.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 1, 1 );
04264 if (rc)
04265 {
04266 if (rc) rc = archive.WriteUuid( m_plugin_id );
04267 if (rc) rc = archive.WriteUuid( m_material_id );
04268
04269
04270
04271
04272
04273
04274
04275 if (rc) rc = archive.WriteInt(0);
04276
04277
04278 if (rc) rc = archive.WriteUuid( m_material_backface_id );
04279 if (rc) rc = archive.WriteInt( m_material_source );
04280
04281
04282 if ( !archive.EndWrite3dmChunk() )
04283 rc = false;
04284 }
04285 return rc;
04286 }
04287
04288 bool ON_MaterialRef::Read( ON_BinaryArchive& archive )
04289 {
04290 Default();
04291 int major_version = 0;
04292 int minor_version = 0;
04293 bool rc = archive.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version );
04294 if (rc)
04295 {
04296 rc = (1 == major_version);
04297
04298 if (rc) rc = archive.ReadUuid( m_plugin_id );
04299 if (rc) rc = archive.ReadUuid( m_material_id );
04300
04301
04302
04303
04304
04305 ON_SimpleArray<ON_MappingChannel> obsolete_mapping_channels;
04306 if (rc) rc = archive.ReadArray( obsolete_mapping_channels );
04307
04308 if ( minor_version >= 1 )
04309 {
04310 if (rc) rc = archive.ReadUuid( m_material_backface_id );
04311 int i = m_material_source;
04312 if (rc) rc = archive.ReadInt( &i );
04313 if (rc) m_material_source = (unsigned char)ON::ObjectMaterialSource(i);
04314 }
04315
04316 if ( !archive.EndRead3dmChunk() )
04317 rc = false;
04318 }
04319 return rc;
04320 }
04321
04322 ON::object_material_source ON_MaterialRef::MaterialSource() const
04323 {
04324 return ON::ObjectMaterialSource(m_material_source);
04325 }
04326
04327 bool ON_MappingRef::Write( ON_BinaryArchive& archive ) const
04328 {
04329 bool rc = archive.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 1, 0 );
04330 if (rc)
04331 {
04332 if (rc) rc = archive.WriteUuid( m_plugin_id );
04333 if (rc) rc = archive.WriteArray( m_mapping_channels );
04334
04335 if ( !archive.EndWrite3dmChunk() )
04336 rc = false;
04337 }
04338 return rc;
04339 }
04340
04341 bool ON_MappingRef::Read( ON_BinaryArchive& archive )
04342 {
04343 Default();
04344 int major_version = 0;
04345 int minor_version = 0;
04346 bool rc = archive.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version );
04347 if (rc)
04348 {
04349 rc = (1 == major_version);
04350
04351 if (rc) rc = archive.ReadUuid( m_plugin_id );
04352 if (rc) rc = archive.ReadArray( m_mapping_channels );
04353
04354 if ( !archive.EndRead3dmChunk() )
04355 rc = false;
04356 }
04357 return rc;
04358 }
04359
04360 bool ON_MappingRef::Transform( const ON_Xform& xform )
04361 {
04362 int count = m_mapping_channels.Count();
04363 if ( count > 0 )
04364 {
04365 for ( ON_MappingChannel* mapping_channel = m_mapping_channels.Array();
04366 count--;
04367 mapping_channel++ )
04368 {
04369 mapping_channel->m_object_xform = xform*mapping_channel->m_object_xform;
04370 }
04371 }
04372 return true;
04373 }
04374
04375 ON_ObjectRenderingAttributes::ON_ObjectRenderingAttributes()
04376 {
04377 Default();
04378 }
04379
04380 ON_RenderingAttributes::ON_RenderingAttributes()
04381 {
04382 Default();
04383 }
04384
04385 void ON_ObjectRenderingAttributes::Default()
04386 {
04387 ON_RenderingAttributes::Default();
04388 m_mappings.Destroy();
04389 m_bCastsShadows = true;
04390 m_bReceivesShadows = true;
04391 m_bits = 0;
04392 m_reserved1 = 0;
04393 }
04394
04395 void ON_RenderingAttributes::Default()
04396 {
04397 m_materials.Destroy();
04398 }
04399
04400 void ON_ObjectRenderingAttributes::EnableAdvancedTexturePreview(bool b)
04401 {
04402 if ( b )
04403 m_bits |= 1;
04404 else
04405 m_bits &= 0xFE;
04406 }
04407
04408 bool ON_ObjectRenderingAttributes::AdvancedTexturePreview() const
04409 {
04410 return (0 != (1 & m_bits)) ? true : false;
04411 }
04412
04413 bool ON_RenderingAttributes::IsValid( ON_TextLog* text_log ) const
04414 {
04415
04416 int count;
04417 if( (count = m_materials.Count()) > 1 )
04418 {
04419 const ON_MaterialRef* mr = m_materials.Array();
04420 ON_UUID plugin_id;
04421 int i, j;
04422 for ( i = 0; i < count-1; i++ )
04423 {
04424 plugin_id = mr[i].m_plugin_id;
04425 for ( j = i+1; j < count; j++ )
04426 {
04427 if ( !ON_UuidCompare(&plugin_id,&mr[j].m_plugin_id ) )
04428 {
04429 if( text_log )
04430 {
04431 text_log->Print("ON_RenderingAttributes error: m_materials[%d] and m_materials[%d] have the same plug-in id.\n",i,j);
04432 }
04433 return false;
04434 }
04435 }
04436 }
04437 }
04438 return true;
04439 }
04440
04441 bool ON_ObjectRenderingAttributes::IsValid( ON_TextLog* text_log ) const
04442 {
04443 if ( !ON_RenderingAttributes::IsValid(text_log) )
04444 return false;
04445
04446
04447 int count;
04448 if( (count = m_mappings.Count()) > 1 )
04449 {
04450 const ON_MappingRef* mr = m_mappings.Array();
04451 ON_UUID plugin_id;
04452 int i, j;
04453 for ( i = 0; i < count-1; i++ )
04454 {
04455 plugin_id = mr[i].m_plugin_id;
04456 for ( j = i+1; j < count; j++ )
04457 {
04458 if ( !ON_UuidCompare(&plugin_id,&mr[j].m_plugin_id ) )
04459 {
04460 if( text_log )
04461 {
04462 text_log->Print("ON_ObjectRenderingAttributes error: m_mappings[%d] and m_mappings[%d] have the same plug-in id.\n",i,j);
04463 }
04464 return false;
04465 }
04466 }
04467 }
04468 }
04469
04470 return true;
04471 }
04472
04473 int ON_RenderingAttributes::Compare( const ON_RenderingAttributes& other ) const
04474 {
04475 const int count = m_materials.Count();
04476 int rc = count - other.m_materials.Count();
04477 if (!rc)
04478 {
04479 int i;
04480 for ( i = 0; i < count && !rc; i++ )
04481 {
04482 rc = m_materials[i].Compare(other.m_materials[i]);
04483 }
04484 }
04485 return rc;
04486 }
04487
04488 const ON_MaterialRef* ON_RenderingAttributes::MaterialRef( const ON_UUID& plugin_id ) const
04489 {
04490 int count;
04491 if ( (count = m_materials.Count()) > 0 )
04492 {
04493 for ( const ON_MaterialRef* mr = m_materials.Array(); count--; mr++ )
04494 {
04495 if ( plugin_id == mr->m_plugin_id )
04496 return mr;
04497 }
04498 }
04499 return 0;
04500 }
04501
04502 int ON_ObjectRenderingAttributes::Compare( const ON_ObjectRenderingAttributes& other ) const
04503 {
04504 int rc = ON_RenderingAttributes::Compare(other);
04505 if (!rc)
04506 {
04507 int i;
04508 const int count = m_mappings.Count();
04509 rc = other.m_mappings.Count() - count;
04510 for ( i = 0; i < count && !rc; i++ )
04511 {
04512 rc = m_mappings[i].Compare(other.m_mappings[i]);
04513 }
04514 if ( !rc )
04515 {
04516 rc = ((int)(m_bCastsShadows?1:0)) - ((int)(other.m_bCastsShadows?1:0));
04517 if ( !rc )
04518 {
04519 rc = ((int)(m_bReceivesShadows?1:0)) - ((int)(other.m_bReceivesShadows?1:0));
04520 }
04521 if ( !rc )
04522 {
04523 rc = ((int)(AdvancedTexturePreview()?1:0)) - ((int)(other.AdvancedTexturePreview()?1:0));
04524 }
04525 }
04526 }
04527 return rc;
04528 }
04529
04530 bool ON_ObjectRenderingAttributes::Transform( const ON_Xform& xform )
04531 {
04532 int i;
04533 if ( (i = m_mappings.Count()) > 0 )
04534 {
04535 for( ON_MappingRef* mr = m_mappings.Array(); i--; mr++ )
04536 mr->Transform(xform);
04537 }
04538 return true;
04539 }
04540
04541 const ON_MappingRef* ON_ObjectRenderingAttributes::MappingRef(
04542 const ON_UUID& plugin_id ) const
04543 {
04544 int count;
04545 if ( (count = m_mappings.Count()) > 0 )
04546 {
04547 for ( const ON_MappingRef* mr = m_mappings.Array(); count--; mr++ )
04548 {
04549 if ( plugin_id == mr->m_plugin_id )
04550 return mr;
04551 }
04552 }
04553 return 0;
04554 }
04555
04556 ON_MappingRef* ON_ObjectRenderingAttributes::AddMappingRef(
04557 const ON_UUID& plugin_id
04558 )
04559 {
04560 ON_MappingRef* mr = 0;
04561 int count;
04562 if ( (count = m_mappings.Count()) > 0 )
04563 {
04564 for ( mr = const_cast<ON_MappingRef*>(m_mappings.Array()); count--; mr++ )
04565 {
04566 if ( plugin_id == mr->m_plugin_id )
04567 break;
04568 }
04569 }
04570
04571 if ( !mr )
04572 {
04573 mr = &m_mappings.AppendNew();
04574 mr->m_plugin_id = plugin_id;
04575 }
04576
04577 return mr;
04578 }
04579
04580 bool ON_ObjectRenderingAttributes::DeleteMappingRef(
04581 const ON_UUID& plugin_id
04582 )
04583 {
04584 const ON_MappingRef* mr = MappingRef(plugin_id);
04585 if ( mr )
04586 m_mappings.Remove( (int)(mr - m_mappings.Array()) );
04587 return (0 != mr);
04588 }
04589
04590 const ON_MappingChannel* ON_ObjectRenderingAttributes::MappingChannel(
04591 const ON_UUID& plugin_id,
04592 const ON_UUID& mapping_id
04593 ) const
04594 {
04595 const ON_MappingRef* mr = MappingRef(plugin_id);
04596 if ( mr )
04597 {
04598 int count;
04599 if ( (count = mr->m_mapping_channels.Count()) > 0 )
04600 {
04601 for ( const ON_MappingChannel* mc = mr->m_mapping_channels.Array(); count--; mc++ )
04602 {
04603 if ( mapping_id == mc->m_mapping_id )
04604 return mc;
04605 }
04606 }
04607 }
04608 return 0;
04609 }
04610
04611 const ON_MappingChannel* ON_ObjectRenderingAttributes::MappingChannel(
04612 const ON_UUID& plugin_id,
04613 int mapping_channel_id
04614 ) const
04615 {
04616 const ON_MappingRef* mr = MappingRef(plugin_id);
04617 if ( mr )
04618 {
04619 int count;
04620 if ( (count = mr->m_mapping_channels.Count()) > 0 )
04621 {
04622 for ( const ON_MappingChannel* mc = mr->m_mapping_channels.Array(); count--; mc++ )
04623 {
04624 if ( mapping_channel_id == mc->m_mapping_channel_id )
04625 return mc;
04626 }
04627 }
04628 }
04629 return 0;
04630 }
04631
04632
04633
04634 bool ON_ObjectRenderingAttributes::AddMappingChannel(
04635 const ON_UUID& plugin_id,
04636 int mapping_channel_id,
04637 const ON_UUID& mapping_id
04638 )
04639 {
04640 ON_MappingRef* mr = const_cast<ON_MappingRef*>(MappingRef(plugin_id));
04641 if ( !mr )
04642 {
04643 mr = &m_mappings.AppendNew();
04644 mr->m_plugin_id = plugin_id;
04645 ON_MappingChannel& mc = mr->m_mapping_channels.AppendNew();
04646 mc.m_mapping_channel_id = mapping_channel_id;
04647 mc.m_mapping_id = mapping_id;
04648 mc.m_mapping_index = -1;
04649 mc.m_object_xform.Identity();
04650 return true;
04651 }
04652
04653 return mr->AddMappingChannel(mapping_channel_id,mapping_id);
04654 }
04655
04656 bool ON_ObjectRenderingAttributes::DeleteMappingChannel(
04657 const ON_UUID& plugin_id,
04658 int mapping_channel_id
04659 )
04660 {
04661 ON_MappingRef* mr = const_cast<ON_MappingRef*>(MappingRef(plugin_id));
04662 return mr ? mr->DeleteMappingChannel(mapping_channel_id) : false;
04663 }
04664
04665 bool ON_ObjectRenderingAttributes::DeleteMappingChannel(
04666 const ON_UUID& plugin_id,
04667 const ON_UUID& mapping_id
04668 )
04669 {
04670 ON_MappingRef* mr = const_cast<ON_MappingRef*>(MappingRef(plugin_id));
04671 return mr ? mr->DeleteMappingChannel(mapping_id) : false;
04672 }
04673
04674 bool ON_ObjectRenderingAttributes::ChangeMappingChannel(
04675 const ON_UUID& plugin_id,
04676 int old_mapping_channel_id,
04677 int new_mapping_channel_id
04678 )
04679 {
04680 ON_MappingRef* mr = const_cast<ON_MappingRef*>(MappingRef(plugin_id));
04681 return mr ? mr->ChangeMappingChannel(old_mapping_channel_id,new_mapping_channel_id) : false;
04682 }
04683
04684 const ON_MappingChannel* ON_MappingRef::MappingChannel(
04685 const ON_UUID& mapping_id
04686 ) const
04687 {
04688 int count;
04689 if ( (count = m_mapping_channels.Count()) > 0 )
04690 {
04691 for ( const ON_MappingChannel* mc = m_mapping_channels.Array(); count--; mc++ )
04692 {
04693 if ( mapping_id == mc->m_mapping_id )
04694 return mc;
04695 }
04696 }
04697 return 0;
04698 }
04699
04700 const ON_MappingChannel* ON_MappingRef::MappingChannel(
04701 int mapping_channel_id
04702 ) const
04703 {
04704 int count;
04705 if ( (count = m_mapping_channels.Count()) > 0 )
04706 {
04707 for ( const ON_MappingChannel* mc = m_mapping_channels.Array(); count--; mc++ )
04708 {
04709 if ( mapping_channel_id == mc->m_mapping_channel_id )
04710 return mc;
04711 }
04712 }
04713 return 0;
04714 }
04715
04716
04717
04718 bool ON_MappingRef::AddMappingChannel(
04719 int mapping_channel_id,
04720 const ON_UUID& mapping_id
04721 )
04722 {
04723 int i;
04724 if ( (i = m_mapping_channels.Count()) > 0 )
04725 {
04726 for ( const ON_MappingChannel* mc = m_mapping_channels.Array(); i--; mc++ )
04727 {
04728 if ( mapping_channel_id == mc->m_mapping_channel_id )
04729 {
04730
04731
04732 return ( 0 == ON_UuidCompare(&mapping_id,&mc->m_mapping_id) );
04733 }
04734 }
04735 }
04736
04737 ON_MappingChannel& mc = m_mapping_channels.AppendNew();
04738 mc.m_mapping_channel_id = mapping_channel_id;
04739 mc.m_mapping_id = mapping_id;
04740 mc.m_mapping_index = -1;
04741 mc.m_object_xform.Identity();
04742
04743 return true;
04744 }
04745
04746 bool ON_MappingRef::DeleteMappingChannel(int mapping_channel_id)
04747 {
04748 const ON_MappingChannel* mc = MappingChannel(mapping_channel_id);
04749 if ( mc )
04750 {
04751 m_mapping_channels.Remove((int)(mc - m_mapping_channels.Array()));
04752 }
04753 return ( 0 != mc);
04754 }
04755
04756 bool ON_MappingRef::DeleteMappingChannel(const ON_UUID& mapping_id)
04757 {
04758 const ON_MappingChannel* mc = MappingChannel(mapping_id);
04759 if ( mc )
04760 {
04761 m_mapping_channels.Remove((int)(mc - m_mapping_channels.Array()));
04762 }
04763 return ( 0 != mc);
04764 }
04765
04766 bool ON_MappingRef::ChangeMappingChannel(
04767 int old_mapping_channel_id,
04768 int new_mapping_channel_id
04769 )
04770 {
04771 ON_MappingChannel* mc = const_cast<ON_MappingChannel*>(MappingChannel(old_mapping_channel_id));
04772 if ( mc )
04773 {
04774 mc->m_mapping_channel_id = new_mapping_channel_id;
04775 }
04776 return ( 0 != mc );
04777 }
04778
04779 bool ON_RenderingAttributes::Write( ON_BinaryArchive& archive ) const
04780 {
04781 bool rc = archive.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 1, 0 );
04782 if ( !rc )
04783 return false;
04784 for(;;)
04785 {
04786 rc = archive.WriteArray(m_materials);
04787 if ( !rc ) break;
04788
04789 break;
04790 }
04791 if ( !archive.EndWrite3dmChunk() )
04792 rc = false;
04793 return rc;
04794 }
04795
04796 bool ON_RenderingAttributes::Read( ON_BinaryArchive& archive )
04797 {
04798 Default();
04799 int major_version = 0;
04800 int minor_version = 0;
04801 bool rc = archive.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version );
04802 if (!rc)
04803 return false;
04804 for(;;)
04805 {
04806 rc = ( 1 == major_version );
04807 if (!rc) break;
04808 rc = archive.ReadArray(m_materials);
04809 if (!rc) break;
04810
04811 break;
04812 }
04813 if ( !archive.EndRead3dmChunk() )
04814 rc = false;
04815 return rc;
04816 }
04817
04818 bool ON_ObjectRenderingAttributes::Write( ON_BinaryArchive& archive ) const
04819 {
04820 bool rc = archive.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 1, 3 );
04821 if ( !rc )
04822 return false;
04823 for(;;)
04824 {
04825
04826 rc = archive.WriteArray(m_materials);
04827 if ( !rc ) break;
04828 rc = archive.WriteArray(m_mappings);
04829 if ( !rc ) break;
04830
04831
04832 rc = archive.WriteBool(m_bCastsShadows);
04833 if ( !rc ) break;
04834 rc = archive.WriteBool(m_bReceivesShadows);
04835 if ( !rc ) break;
04836
04837
04838 bool b = AdvancedTexturePreview();
04839 rc = archive.WriteBool(b);
04840 if ( !rc ) break;
04841
04842 break;
04843 }
04844 if ( !archive.EndWrite3dmChunk() )
04845 rc = false;
04846 return rc;
04847 }
04848
04849 bool ON_ObjectRenderingAttributes::Read( ON_BinaryArchive& archive )
04850 {
04851 Default();
04852 int major_version = 0;
04853 int minor_version = 0;
04854 bool rc = archive.BeginRead3dmChunk( TCODE_ANONYMOUS_CHUNK, &major_version, &minor_version );
04855 if (!rc)
04856 return false;
04857 for(;;)
04858 {
04859 rc = ( 1 == major_version && minor_version >= 1 );
04860 if (!rc) break;
04861
04862
04863 if (rc) rc = archive.ReadArray(m_materials);
04864 if (!rc) break;
04865 if (rc) rc = archive.ReadArray(m_mappings);
04866 if (!rc) break;
04867
04868 if ( minor_version <= 1 )
04869 break;
04870
04871
04872 rc = archive.ReadBool(&m_bCastsShadows);
04873 if ( !rc ) break;
04874 rc = archive.ReadBool(&m_bReceivesShadows);
04875 if ( !rc ) break;
04876
04877 if ( minor_version <= 2 )
04878 break;
04879
04880
04881 bool b = AdvancedTexturePreview();
04882 rc = archive.ReadBool(&b);
04883 if ( !rc ) break;
04884
04885
04886
04887
04888 break;
04889 }
04890 if ( !archive.EndRead3dmChunk() )
04891 rc = false;
04892
04893 return rc;
04894 }
04895
04896
04897 bool ON_TextureMapping::SetSurfaceParameterMapping(void)
04898 {
04899 Default();
04900 m_type = srfp_mapping;
04901 ON_CreateUuid(m_mapping_id);
04902 return true;
04903 }
04904
04905
04906 bool ON_TextureMapping::SetPlaneMapping(
04907 const ON_Plane& plane,
04908 const ON_Interval& dx,
04909 const ON_Interval& dy,
04910 const ON_Interval& dz
04911 )
04912 {
04913 Default();
04914
04915
04916
04917
04918 if ( !plane.origin.IsValid() )
04919 return false;
04920 if ( !ON_IsRightHandFrame( plane.xaxis, plane.yaxis, plane.zaxis ) )
04921 return false;
04922 if ( !dx.IsValid() || !dy.IsValid() || !dz.IsValid() )
04923 return false;
04924
04925 ON_3dPoint C = plane.PointAt(dx.Mid(),dy.Mid(),dz.Mid());
04926 C.x = (0.0 == C.x) ? 0.0 : -C.x;
04927 C.y = (0.0 == C.y) ? 0.0 : -C.y;
04928 C.z = (0.0 == C.z) ? 0.0 : -C.z;
04929 ON_3dVector xaxis = plane.xaxis;
04930 ON_3dVector yaxis = plane.yaxis;
04931 ON_3dVector zaxis = plane.zaxis;
04932
04933
04934
04935
04936 double sx,sy,sz;
04937 if ( 0.0 == (sx = dx.Length())) sx = 2.0;
04938 if ( 0.0 == (sy = dy.Length())) sy = 2.0;
04939 if ( 0.0 == (sz = dz.Length())) sz = 2.0;
04940
04941
04942
04943
04944
04945
04946
04947
04948 ON_3dVector X = (2.0/sx)*xaxis;
04949 ON_3dVector Y = (2.0/sy)*yaxis;
04950 ON_3dVector Z = (2.0/sz)*zaxis;
04951
04952 m_Pxyz.m_xform[0][0] = X.x;
04953 m_Pxyz.m_xform[0][1] = X.y;
04954 m_Pxyz.m_xform[0][2] = X.z;
04955 m_Pxyz.m_xform[0][3] = (X.x*C.x + X.y*C.y + X.z*C.z);
04956
04957 m_Pxyz.m_xform[1][0] = Y.x;
04958 m_Pxyz.m_xform[1][1] = Y.y;
04959 m_Pxyz.m_xform[1][2] = Y.z;
04960 m_Pxyz.m_xform[1][3] = (Y.x*C.x + Y.y*C.y + Y.z*C.z);
04961
04962 m_Pxyz.m_xform[2][0] = Z.x;
04963 m_Pxyz.m_xform[2][1] = Z.y;
04964 m_Pxyz.m_xform[2][2] = Z.z;
04965 m_Pxyz.m_xform[2][3] = (Z.x*C.x + Z.y*C.y + Z.z*C.z);
04966
04967 m_Pxyz.m_xform[3][0] = 0.0;
04968 m_Pxyz.m_xform[3][1] = 0.0;
04969 m_Pxyz.m_xform[3][2] = 0.0;
04970 m_Pxyz.m_xform[3][3] = 1.0;
04971
04972
04973
04974 X = (0.5*sx)*xaxis;
04975 Y = (0.5*sy)*yaxis;
04976 Z = (0.5*sz)*zaxis;
04977 m_Nxyz.m_xform[0][0] = X.x;
04978 m_Nxyz.m_xform[0][1] = X.y;
04979 m_Nxyz.m_xform[0][2] = X.z;
04980 m_Nxyz.m_xform[0][3] = 0.0;
04981
04982 m_Nxyz.m_xform[1][0] = Y.x;
04983 m_Nxyz.m_xform[1][1] = Y.y;
04984 m_Nxyz.m_xform[1][2] = Y.z;
04985 m_Nxyz.m_xform[1][3] = 0.0;
04986
04987 m_Nxyz.m_xform[2][0] = Z.x;
04988 m_Nxyz.m_xform[2][1] = Z.y;
04989 m_Nxyz.m_xform[2][2] = Z.z;
04990 m_Nxyz.m_xform[2][3] = 0.0;
04991
04992 m_Nxyz.m_xform[3][0] = 0.0;
04993 m_Nxyz.m_xform[3][1] = 0.0;
04994 m_Nxyz.m_xform[3][2] = 0.0;
04995 m_Nxyz.m_xform[3][3] = 1.0;
04996
04997 m_type = plane_mapping;
04998 ON_CreateUuid(m_mapping_id);
04999
05000 #if defined(ON_DEBUG)
05001 {
05002 ON_Plane p;
05003 p.xaxis = (2.0/sx)*plane.xaxis;
05004 p.yaxis = (2.0/sy)*plane.yaxis;
05005 p.zaxis = (2.0/sz)*plane.zaxis;
05006 p.origin.Set(-C.x,-C.y,-C.z);
05007 p.UpdateEquation();
05008 ON_Xform P_dbg, N_dbg;
05009 P_dbg.Rotation(p,ON_xy_plane);
05010 P_dbg.GetSurfaceNormalXform(N_dbg);
05011
05012 for ( int i = 0; i < 4; i++ )
05013 {
05014 for ( int j = 0; j < 4; j++ )
05015 {
05016 if ( fabs(m_Pxyz[i][j] - P_dbg[i][j]) >= ON_SQRT_EPSILON*(fabs(m_Pxyz[i][j])+128.0) )
05017 {
05018 ON_ERROR("m_Pxyz is nor right\n");
05019 break;
05020 }
05021 if ( fabs(m_Nxyz[i][j] - N_dbg[i][j]) >= ON_SQRT_EPSILON*(fabs(m_Nxyz[i][j])+128.0) )
05022 {
05023 ON_ERROR("m_Nxyz is nor right\n");
05024 break;
05025 }
05026 }
05027 }
05028 }
05029 #endif
05030 return true;
05031 }
05032
05033 bool ON_TextureMapping::SetBoxMapping(const ON_Plane& plane,
05034 ON_Interval dx,
05035 ON_Interval dy,
05036 ON_Interval dz,
05037 bool bCapped
05038 )
05039 {
05040 bool rc = SetPlaneMapping(plane,dx,dy,dz);
05041 if (rc)
05042 {
05043 m_bCapped = bCapped;
05044 m_type = ON_TextureMapping::box_mapping;
05045 }
05046 return rc;
05047 }
05048
05049 bool ON_TextureMapping::SetCylinderMapping(const ON_Cylinder& cylinder, bool bIsCapped)
05050 {
05051 ON_Interval dr, dh;
05052 if ( !ON_IsValid(cylinder.circle.radius ) )
05053 return false;
05054 double r = cylinder.circle.radius;
05055 if ( 0.0 == r )
05056 r = 1.0;
05057 dr.Set(-r,r);
05058 dh.Set(cylinder.height[0],cylinder.height[1]);
05059 if ( dh[0] == dh[1] )
05060 {
05061 if ( ON_UNSET_VALUE == dh[0] )
05062 {
05063 dh.Set(-1.0,1.0);
05064 }
05065 else
05066 {
05067 dh.m_t[0] -= 1.0;
05068 dh.m_t[0] += 1.0;
05069 }
05070 }
05071 if ( !dh.IsValid() )
05072 return false;
05073
05074 bool rc = SetBoxMapping(cylinder.circle.plane,dr,dr,dh,bIsCapped);
05075 if (rc)
05076 {
05077 m_type = cylinder_mapping;
05078 }
05079
05080 return rc;
05081 }
05082
05083 bool ON_TextureMapping::SetSphereMapping(const ON_Sphere& sphere)
05084 {
05085 ON_Interval dr(-sphere.radius,sphere.radius);
05086 bool rc = SetBoxMapping(sphere.plane,dr,dr,dr,false);
05087 if (rc)
05088 {
05089 m_type = sphere_mapping;
05090 }
05091 return rc;
05092 }
05093
05094
05095
05096 bool ON_TextureMapping::GetMappingPlane(ON_Plane& plane,
05097 ON_Interval& dx,
05098 ON_Interval& dy,
05099 ON_Interval& dz
05100 ) const
05101 {
05102 ON_Xform xform(m_Pxyz);
05103
05104 ON_3dVector S(((ON_3dVector*)&xform.m_xform[0])->Length(),
05105 ((ON_3dVector*)&xform.m_xform[1])->Length(),
05106 ((ON_3dVector*)&xform.m_xform[2])->Length());
05107
05108 if ( 0.0 == S.x )
05109 return false;
05110 S.x = 1.0/S.x;
05111 if ( 0.0 == S.y )
05112 return false;
05113 S.y = 1.0/S.y;
05114 if ( 0.0 == S.z )
05115 return false;
05116 S.z = 1.0/S.z;
05117
05118 xform.m_xform[0][0] *= S.x; xform.m_xform[0][1] *= S.x; xform.m_xform[0][2] *= S.x;
05119 xform.m_xform[0][3] *= S.x;
05120
05121 xform.m_xform[1][0] *= S.y; xform.m_xform[1][1] *= S.y; xform.m_xform[1][2] *= S.y;
05122 xform.m_xform[1][3] *= S.y;
05123
05124 xform.m_xform[2][0] *= S.z; xform.m_xform[2][1] *= S.z; xform.m_xform[2][2] *= S.z;
05125 xform.m_xform[2][3] *= S.z;
05126
05127 xform.m_xform[3][0] = 0.0;
05128 xform.m_xform[3][1] = 0.0;
05129 xform.m_xform[3][2] = 0.0;
05130 xform.m_xform[3][3] = 1.0;
05131
05132 ON_Xform inv(xform);
05133 if ( !inv.Invert() )
05134 return false;
05135
05136 plane.origin.Set(inv.m_xform[0][3],inv.m_xform[1][3],inv.m_xform[2][3]);
05137 xform.m_xform[0][3] = 0.0;
05138 xform.m_xform[1][3] = 0.0;
05139 xform.m_xform[2][3] = 0.0;
05140 plane.xaxis = &xform.m_xform[0][0];
05141 plane.yaxis = &xform.m_xform[1][0];
05142 plane.zaxis = &xform.m_xform[2][0];
05143
05144 plane.UpdateEquation();
05145
05146 dx.Set(-S.x,S.x);
05147 dy.Set(-S.y,S.y);
05148 dz.Set(-S.z,S.z);
05149
05150 return plane.IsValid();
05151 }
05152
05153 bool ON_TextureMapping::GetMappingBox(ON_Plane& plane,
05154 ON_Interval& dx,
05155 ON_Interval& dy,
05156 ON_Interval& dz) const
05157 {
05158 return GetMappingPlane(plane, dx, dy, dz);
05159 }
05160
05161 bool ON_TextureMapping::GetMappingCylinder(ON_Cylinder& cylinder) const
05162 {
05163 ON_Interval dx, dy, dz;
05164 ON_Plane plane;
05165 bool rc = GetMappingPlane(cylinder.circle.plane, dx, dy, dz);
05166 if (rc)
05167 {
05168 double r0 = 0.5*dx.Length();
05169 double r1 = 0.5*dy.Length();
05170 cylinder.circle.radius = (r0 == r1) ? r0 : 0.5*(r0+r1);
05171 cylinder.height[0] = dz[0];
05172 cylinder.height[1] = dz[1];
05173 }
05174
05175 return rc && cylinder.IsValid();
05176 }
05177
05178 bool ON_TextureMapping::GetMappingSphere(ON_Sphere& sphere) const
05179 {
05180 ON_Interval dx, dy, dz;
05181 bool rc = GetMappingPlane(sphere.plane, dx, dy, dz);
05182 if (rc)
05183 {
05184 double r0 = 0.5*dx.Length();
05185 double r1 = 0.5*dy.Length();
05186 double r2 = 0.5*dz.Length();
05187 sphere.radius = (r0 == r1 && r0 == r2) ? r0 : (r0+r1+r2)/3.0;
05188 }
05189 return rc && sphere.IsValid();
05190 }
05191