00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "ioblock.H"
00010 #include "gtexture.H"
00011 #include "bfilters.H"
00012 #include "patch.H"
00013 #include "std/config.H"
00014 #include "sps/sps.H"
00015
00016
00017 init_fade_func_t Patch::_init_fade = 0;
00018
00019 TAGlist* Patch::_patch_tags = 0;
00020 int Patch::_next_stencil_id = 0;
00021
00022
00023 Patch::Patch(BMESH* mesh) :
00024 _mesh(mesh),
00025 _faces(0),
00026 _creases(0),
00027 _borders(0),
00028 _textures(0),
00029 _cur_tex_i(0),
00030 _non_tex_i(0),
00031 _prev_tex(0),
00032 _pixels(0),
00033 _stamp(0),
00034 _mesh_version(0),
00035 _tri_strips_dirty(1),
00036 _tex_coord_gen(0),
00037 _data(0),
00038 _stencil_id(0),
00039 _scale(1.0),
00040 _o(PIXEL(0,0)),
00041 _u_o(PIXEL(1,0)),
00042 _v_o(PIXEL(0,1)),
00043 _dynamic_stamp(UINT_MAX),
00044 _do_dynamic_stuff(true),
00045 _do_lod(true),
00046 _lod_t(0)
00047 {
00048 _textures.set_unique();
00049
00050
00051
00052
00053
00054
00055 if (_mesh)
00056 _mesh->changed(BMESH::RENDERING_CHANGED);
00057
00058 set_name(str_ptr("patch-") + str_ptr(_mesh->patches().num()));
00059 }
00060
00061 Patch::~Patch()
00062 {
00063
00064 _textures.delete_all();
00065
00066
00067 if (_mesh) _mesh->unlist(this);
00068 _mesh = 0;
00069
00070
00071
00072
00073 while (!_tri_strips.empty())
00074 delete _tri_strips.pop();
00075 delete _creases;
00076 delete _borders;
00077
00078
00079
00080
00081
00082
00083 for (int i=0; i<_faces.num(); i++) {
00084 _faces[i]->set_patch(0);
00085 _faces[i]->set_patch_index(-1);
00086 }
00087 }
00088
00089 void
00090 Patch::triangulation_changed()
00091 {
00092 _tri_strips_dirty = 1;
00093
00094 creases_changed();
00095 borders_changed();
00096
00097 changed();
00098 }
00099
00100 void
00101 Patch::creases_changed()
00102 {
00103 delete _creases;
00104 _creases = 0;
00105 }
00106
00107 void
00108 Patch::borders_changed()
00109 {
00110 delete _borders;
00111 _borders = 0;
00112 }
00113
00114
00115 EdgeStrip&
00116 Patch::build_sils()
00117 {
00118
00119 _mesh->build_sil_strips();
00120
00121 return _sils;
00122 }
00123
00124 ZcrossPath&
00125 Patch::build_zx_sils()
00126 {
00127
00128 _mesh->build_zcross_strips();
00129
00130 return _zx_sils;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 EdgeStrip*
00141 Patch::build_edge_strip(EdgeStrip* strip, CSimplexFilter& filter)
00142 {
00143
00144 if (strip) {
00145 strip->reset();
00146 strip->build_with_tips(edges(), filter + PatchEdgeFilter(this));
00147 }
00148 return strip;
00149 }
00150
00151 EdgeStrip*
00152 Patch::build_creases()
00153 {
00154
00155 if (_creases)
00156 return _creases;
00157
00158
00159
00160 _creases = _mesh ? _mesh->new_edge_strip() : new EdgeStrip();
00161
00162
00163 return build_edge_strip(_creases, CreaseEdgeFilter());
00164 }
00165
00166 EdgeStrip*
00167 Patch::build_borders()
00168 {
00169
00170 if (_borders)
00171 return _borders;
00172
00173
00174
00175 _borders = _mesh ? _mesh->new_edge_strip() : new EdgeStrip();
00176
00177
00178 return build_edge_strip(_borders, BorderEdgeFilter());
00179 }
00180
00181 Bvert_list
00182 Patch::verts() const
00183 {
00184
00185
00186 assert(_mesh);
00187
00188
00189 if (_mesh->nfaces() == _faces.num() &&
00190 !(_mesh->is_polylines() || _mesh->is_points()))
00191 return _mesh->verts();
00192
00193 return _faces.get_verts();
00194 }
00195
00196 Bedge_list
00197 Patch::edges() const
00198 {
00199
00200
00201 assert(_mesh);
00202
00203
00204 if (_mesh->nfaces() == _faces.num() && !_mesh->is_polylines())
00205 return _mesh->edges();
00206
00207 return _faces.get_edges();
00208 }
00209
00210
00211 void
00212 Patch::add(Bface* f)
00213 {
00214
00215 if (!f || f->patch() == this)
00216 return;
00217
00218
00219 if (f->patch())
00220 f->patch()->remove(f);
00221
00222
00223 f->set_patch_index(_faces.num());
00224 _faces += f;
00225 f->set_patch(this);
00226
00227 triangulation_changed();
00228 }
00229
00230 void
00231 Patch::remove(Bface* f)
00232 {
00233 if (!(f && f->patch() == this)) {
00234 err_msg("Patch::remove: error: face is NULL or not owned by this Patch");
00235 return;
00236 }
00237
00238 int k = f->patch_index();
00239 if (_faces.valid_index(k)) {
00240 _faces.remove(k);
00241 _faces[k]->set_patch_index(k);
00242 }
00243 f->set_patch_index(-1);
00244 f->set_patch(0);
00245 triangulation_changed();
00246 }
00247
00248 void
00249 Patch::add(VertStrip* vs)
00250 {
00251 if (vs->patch())
00252 vs->patch()->remove(vs);
00253 vs->set_patch(this);
00254 vs->set_patch_index(_vert_strips.num());
00255 _vert_strips += vs;
00256 changed();
00257 }
00258
00259 void
00260 Patch::remove(VertStrip* vs)
00261 {
00262 assert(vs->patch() == this);
00263 int k = vs->patch_index();
00264 if (_vert_strips.valid_index(k)) {
00265 _vert_strips.remove(k);
00266 _vert_strips[k]->set_patch_index(k);
00267 changed();
00268 }
00269 vs->set_patch_index(-1);
00270 vs->set_patch(0);
00271 }
00272
00273 void
00274 Patch::add(EdgeStrip* es)
00275 {
00276 if (es->patch())
00277 es->patch()->remove(es);
00278 es->set_patch(this);
00279 es->set_patch_index(_edge_strips.num());
00280 _edge_strips += es;
00281 changed();
00282 }
00283
00284 void
00285 Patch::remove(EdgeStrip* es)
00286 {
00287 assert(es->patch() == this);
00288 int k = es->patch_index();
00289 if (_edge_strips.valid_index(k)) {
00290 _edge_strips.remove(k);
00291 _edge_strips[k]->set_patch_index(k);
00292 changed();
00293 }
00294 es->set_patch_index(-1);
00295 es->set_patch(0);
00296 }
00297
00298 void
00299 Patch::build_tri_strips()
00300 {
00301 if (_tri_strips_dirty) {
00302 _tri_strips_dirty = 0;
00303
00304
00305 int k;
00306 for (k=0; k<_tri_strips.num(); k++)
00307 delete _tri_strips[k];
00308 _tri_strips.clear();
00309
00310
00311 for (k=0; k<_faces.num(); k++) {
00312 _faces[k]->clear_flag();
00313 _faces[k]->orient_strip(0);
00314 }
00315
00316
00317
00318 if (!BMESH::show_secondary_faces())
00319 _faces.secondary_faces().set_flags(1);
00320
00321 for (k=0; k<_faces.num(); k++)
00322 if (!_faces[k]->flag())
00323 TriStrip::get_strips(_faces[k], _tri_strips);
00324
00325 static bool debug = Config::get_var_bool("PRINT_TRIS_PER_STRIP",false);
00326 if (debug)
00327 err_msg("tris/strip: %1.1f", tris_per_strip());
00328 }
00329 }
00330
00331
00332 int
00333 Patch::draw(CVIEWptr& v)
00334 {
00335 GTexture* cur = cur_tex(v);
00336 if (!cur)
00337 return 0;
00338
00339
00340
00341 static const double FADE_DUR = Config::get_var_dbl("FADE_DUR", 0.5,true);
00342 if (_prev_tex && _prev_tex != cur && _init_fade)
00343 (*_init_fade)(cur, _prev_tex, v->frame_time(), FADE_DUR);
00344 _prev_tex = cur;
00345 int ret = cur->draw(v);
00346 _pixels.clear();
00347 return ret;
00348 }
00349
00350 int
00351 Patch::draw_tri_strips(StripCB* cb)
00352 {
00353 build_tri_strips();
00354
00355 for (int k=0; k<_tri_strips.num(); k++)
00356 _tri_strips[k]->draw(cb);
00357
00358 return _faces.num();
00359 }
00360
00361 int
00362 Patch::draw_sil_strips(StripCB *cb)
00363 {
00364 cur_sils().draw(cb);
00365 return cur_sils().num();
00366 }
00367
00368 int
00369 Patch::draw_crease_strips(StripCB *cb)
00370 {
00371 EdgeStrip* strip = cur_creases();
00372 if (strip)
00373 strip->draw(cb);
00374 return 0;
00375 }
00376
00377 int
00378 Patch::draw_edge_strips(StripCB *cb)
00379 {
00380
00381
00382 int ret=0;
00383
00384
00385 for (int i=0; i<_edge_strips.num(); i++) {
00386 _edge_strips[i]->draw(cb);
00387 ret += _edge_strips[i]->num();
00388 }
00389
00390 return ret;
00391 }
00392
00393 int
00394 Patch::draw_vert_strips(StripCB *cb)
00395 {
00396 int ret=0;
00397
00398
00399 for (int i=0; i<_vert_strips.num(); i++) {
00400 _vert_strips[i]->draw(cb);
00401 ret += _vert_strips[i]->num();
00402 }
00403
00404 return ret;
00405 }
00406
00407
00408 void
00409 Patch::set_texture(GTexture* gtex)
00410 {
00411 if (!gtex) {
00412 err_msg("Patch::set_texture: can't set nil texture");
00413 return;
00414 }
00415 _textures.add_uniquely(gtex);
00416 _cur_tex_i = _textures.get_index(gtex);
00417
00418 }
00419
00420 void
00421 Patch::set_texture(Cstr_ptr& style)
00422 {
00423 _cur_tex_i = get_tex_index(style);
00424
00425 }
00426
00427 void
00428 Patch::next_texture()
00429 {
00430 _cur_tex_i = (_cur_tex_i + 1) % _textures.num();
00431
00432 }
00433
00434
00435
00436
00437
00438
00439 GTexture*
00440 Patch::find_tex(Cstr_ptr& tex_name) const
00441 {
00442
00443
00444 str_ptr temp_tex_name;
00445 if(tex_name == "FFSTexture2")
00446 temp_tex_name = "FFSTexture";
00447 else
00448 temp_tex_name = tex_name;
00449
00450 for (int i=0; i<_textures.num(); i++)
00451 if (_textures[i]->type() == temp_tex_name)
00452 return _textures[i];
00453
00454 return 0;
00455 }
00456
00457
00458
00459
00460
00461
00462 GTexture*
00463 Patch::get_tex(Cstr_ptr& tex_name)
00464 {
00465
00466
00467 GTexture* tex = find_tex(tex_name);
00468 if (tex)
00469 return tex;
00470
00471
00472 tex = (GTexture*)DATA_ITEM::lookup(tex_name);
00473 if (!tex)
00474 return 0;
00475
00476
00477 if ((tex = (GTexture*)tex->dup())) {
00478 tex->set_patch(this);
00479 _textures += tex;
00480 return tex;
00481 } else {
00482 err_msg("Patch::get_tex: tex->dup() returned nil");
00483 return 0;
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 GTexture*
00496 Patch::cur_tex(CVIEWptr& v)
00497 {
00498
00499
00500 str_ptr tex_name =
00501 (_mesh->render_style() == str_ptr::null_str()) ?
00502 v->rendering() :
00503 _mesh->render_style();
00504
00505 if (tex_name == GTexture::static_name()) {
00506 GTexture* tex = cur_tex();
00507 if (tex)
00508 return tex;
00509
00510
00511
00512 tex_name = RFLAT_SHADE;
00513 }
00514
00515 return get_tex(tex_name);
00516 }
00517
00518
00519 int
00520 Patch::write_stream(ostream &os)
00521 {
00522
00523
00524
00525
00526
00527
00528 if (_faces.empty())
00529 return 0;
00530
00531 assert(_mesh != NULL);
00532
00533 os << "#BEGIN PATCH" << endl;
00534
00535
00536
00537
00538 if (_faces.num() > _mesh->nfaces()) {
00539
00540
00541 assert(0);
00542
00543 } else if (_faces.num() == _mesh->nfaces()) {
00544
00545
00546
00547 os << (int)0 << endl;
00548
00549 } else {
00550
00551
00552
00553 CBface_list& cfaces = cur_faces();
00554
00555
00556 os << cfaces.num() << endl;
00557
00558 for (int f=0; f<cfaces.num(); f++) {
00559 assert(get_ctrl_patch(cfaces[f]) == this);
00560 os << cfaces[f]->index() << endl;
00561 }
00562 }
00563
00564
00565 os << endl<< _cur_tex_i << endl;
00566 _textures.write_stream(os);
00567
00568
00569 if (_name != NULL_STR) {
00570 os << "#BEGIN PATCHNAME" << endl;
00571 os << _name << endl;
00572 os << "#END PATCHNAME" << endl;
00573 }
00574
00575
00576 if (_has_color) {
00577 os << "#BEGIN COLOR" << endl;
00578 os << _color << endl;
00579 os << "#END COLOR" << endl;
00580 }
00581
00582
00583 if (has_texture()) {
00584 os << "#BEGIN TEXTURE_MAP" << endl;
00585 os << _texture->file() << endl;
00586 os << "#END TEXTURE_MAP" << endl;
00587 }
00588
00589 os << "#END PATCH" << endl;
00590
00591 return 1;
00592 }
00593
00594 int
00595 Patch::read_stream(istream &is, str_list &leftover)
00596 {
00597 leftover.clear();
00598
00599 int num_faces;
00600 is >> num_faces;
00601
00602 bool debug = Config::get_var_bool("DEBUG_PATCH_READ_STREAM",false);
00603 if (debug)
00604 err_msg("\n********\nPatch::read_stream: %d faces to read", num_faces);
00605
00606 if (num_faces > 0) {
00607
00608 if (debug)
00609 err_msg("Patch::read_stream: reading %d faces from file", num_faces);
00610
00611
00612 int face;
00613 for (int f = 0; f < num_faces; f++) {
00614 is >> face;
00615 if (face < _mesh->nfaces()) {
00616 add(_mesh->bf(face));
00617 } else {
00618 cerr << "Patch::read_stream - face " << face << " > "
00619 << _mesh->nfaces()
00620 << ", at byte " << is.tellg() << endl;
00621 }
00622 }
00623 } else {
00624 if (debug)
00625 err_msg("Patch::read_stream: using all %d faces of mesh",
00626 _mesh->nfaces());
00627
00628 for (int f = 0; f < _mesh->nfaces(); f++)
00629 add(_mesh->bf(f));
00630 }
00631
00632 is >> _cur_tex_i;
00633 if (debug)
00634 err_msg("Patch::read_stream: cur texture is number %d", _cur_tex_i);
00635
00636
00637 GTexture_list tmp_textures = _textures;
00638
00639 _textures.clear();
00640
00641
00642
00643 static IOBlockList blocklist;
00644 if (blocklist.num() == 0) {
00645 blocklist += new IOBlockMeth<Patch>("GTEXTURE", &Patch::read_texture,
00646 this);
00647 blocklist += new IOBlockMeth<Patch>("COLOR", &Patch::read_color,
00648 this);
00649 blocklist += new IOBlockMeth<Patch>("TEXTURE_MAP",
00650 &Patch::read_texture_map,
00651 this);
00652 blocklist += new IOBlockMeth<Patch>("PATCHNAME",&Patch::read_patchname,
00653 this);
00654 } else {
00655 for (int i = 0; i < blocklist.num(); i++) {
00656 ((IOBlockMeth<Patch> *) blocklist[i])->set_obj(this);
00657 }
00658 }
00659 int ret = IOBlock::consume(is, blocklist, leftover);
00660
00661 changed();
00662
00663 if (_textures.num() > 0) {
00664
00665 if (debug) {
00666 err_msg("Patch::read_stream: read %d textures", _textures.num());
00667 err_msg(" ... deleting %d old textures", tmp_textures.num());
00668 }
00669
00670
00671 tmp_textures.delete_all();
00672
00673 } else {
00674
00675 if (debug)
00676 err_msg("Patch::read_stream: read 0 textures, keeping old ones");
00677
00678
00679 _textures = tmp_textures;
00680 }
00681
00682 return ret;
00683 }
00684
00685 int
00686 Patch::read_texture(istream &is, str_list &leftover)
00687 {
00688 leftover.clear();
00689 const int namelen = 256;
00690 char name1[namelen];
00691 char name[namelen];
00692 char *wherecr;
00693 is.getline(name1, namelen);
00694 is.getline(name, namelen);
00695
00696
00697
00698 while ((wherecr = strchr(name, '\015'))) {
00699 *wherecr = 0;
00700 }
00701 int texnum = get_tex_index(name);
00702 if (texnum < 0) {
00703
00704
00705 while (strrchr(name, ' ') == name + strlen(name) - 1) {
00706 name[strlen(name) - 1] = '\0';
00707 }
00708 texnum = get_tex_index(name);
00709 }
00710 GTexture* tex = texnum >= 0 ? _textures[texnum] : 0;
00711 if (!tex) {
00712 cerr << "Patch::read_texture - could not find GTexture '"
00713 << name << "' (skipping)" << endl;
00714 return 1;
00715 }
00716
00717 return tex->read_stream(is, leftover);
00718 }
00719
00720 int
00721 Patch::read_color(istream &is, str_list &leftover)
00722 {
00723 leftover.clear();
00724
00725 COLOR c;
00726 is >> c;
00727 set_color(c);
00728
00729 return 1;
00730 }
00731
00732 int
00733 Patch::read_texture_map(istream &is, str_list &leftover)
00734 {
00735 leftover.clear();
00736
00737 char buf[126];
00738 is >> buf;
00739 _texture_file = str_ptr(buf);
00740
00741 return 1;
00742 }
00743
00744 int
00745 Patch::read_patchname(istream &is, str_list &leftover)
00746 {
00747 leftover.clear();
00748 const int namelen = 256;
00749 char name[256];
00750 is.getline(name, namelen);
00751 is.getline(name, namelen);
00752 set_name(name);
00753
00754 return 1;
00755 }
00756
00757
00758 RefImageClient::ref_img_t
00759 Patch::use_ref_image()
00760 {
00761 GTexture* tex = cur_tex(VIEW::peek());
00762 return tex ? tex->use_ref_image() : REF_IMG_NONE;
00763 }
00764
00765 int
00766 Patch::draw_vis_ref()
00767 {
00768 GTexture* tex = cur_tex(VIEW::peek());
00769 return tex ? tex->draw_vis_ref() : 0;
00770 }
00771
00772 int
00773 Patch::draw_ref_img(ref_img_t t)
00774 {
00775 GTexture* tex = cur_tex(VIEW::peek());
00776 return tex ? tex->draw_ref_img(t) : 0;
00777 }
00778
00779 int
00780 Patch::draw_final(CVIEWptr &v)
00781 {
00782 GTexture* tex = cur_tex(VIEW::peek());
00783 return tex ? tex->draw_final(v) : 0;
00784 }
00785
00786
00787 CTAGlist &
00788 Patch::tags() const
00789 {
00790 if (!_patch_tags) {
00791 _patch_tags = new TAGlist(0);
00792 *_patch_tags += new TAG_meth<Patch> ("faces", &Patch::put_faces,
00793 &Patch::get_faces, 1);
00794
00795 *_patch_tags += new TAG_val<Patch,int>("cur_tex", &Patch::cur_tex_i_);
00796 *_patch_tags += new TAG_val<Patch,str_ptr>("patchname", &Patch::name_);
00797
00798
00799
00800 *_patch_tags += new TAG_meth<Patch> ("color", &Patch::put_color,
00801 &Patch::get_color, 0);
00802
00803
00804 *_patch_tags += new TAG_meth<Patch> ("texture", &Patch::put_textures,
00805 &Patch::get_texture, 1);
00806 }
00807 return *_patch_tags;
00808 }
00809
00810 DATA_ITEM*
00811 Patch::dup() const
00812 {
00813
00814
00815 return 0;
00816 }
00817
00818
00819
00820 CCOLOR &
00821 Patch::color() const
00822 {
00823 return APPEAR::color();
00824 }
00825
00826 bool
00827 Patch::has_color() const
00828 {
00829 return APPEAR::has_color();
00830 }
00831
00832 void
00833 Patch::set_color(CCOLOR &c)
00834 {
00835
00836 if (has_color() && color().is_equal(c))
00837 return;
00838
00839 APPEAR::set_color(c);
00840 }
00841
00842 void
00843 Patch::unset_color()
00844 {
00845 APPEAR::unset_color();
00846 }
00847
00848 double
00849 Patch::transp() const
00850 {
00851 return APPEAR::transp();
00852 }
00853
00854 bool
00855 Patch::has_transp() const
00856 {
00857 return APPEAR::has_transp();
00858 }
00859
00860 void
00861 Patch::set_transp(double t)
00862 {
00863 APPEAR::set_transp(t);
00864 }
00865
00866 void
00867 Patch::unset_transp()
00868 {
00869 APPEAR::unset_transp();
00870 }
00871
00872 void
00873 Patch::set_texture(CTEXTUREptr& t)
00874 {
00875 APPEAR::set_texture(t);
00876 changed();
00877 }
00878
00879 void
00880 Patch::unset_texture()
00881 {
00882 APPEAR::unset_texture();
00883 changed();
00884 }
00885
00886 void
00887 Patch::get_texture(TAGformat &d)
00888 {
00889 str_ptr str, str1;
00890 *d >> str;
00891
00892 if ((*d).ascii())
00893 {
00894 while (str1 = (*d).get_string_with_spaces())
00895 {
00896 str = str + " " + str1;
00897 }
00898 }
00899
00900 int texnum = get_tex_index(str);
00901
00902 if (texnum < 0)
00903 {
00904 err_msg("Patch::get_texture() - ERROR! Could not find texture '%s'", **str);
00905 return;
00906 }
00907
00908 GTexture* tex = _textures[texnum]; assert(tex);
00909
00910 err_mesg(ERR_LEV_SPAM, "Patch::get_texture() - Loaded: '%s'", **str);
00911
00912 tex->decode(*d);
00913
00914 }
00915
00916 void
00917 Patch::put_textures(TAGformat &d) const
00918 {
00919 for (int t = 0; t < _textures.num(); t++)
00920 {
00921 err_mesg(ERR_LEV_SPAM, "Patch::put_textures() - Writing texture #%d '%s'",
00922 t, **_textures[t]->class_name());
00923 d.id();
00924 _textures[t]->format(*d);
00925 d.end_id();
00926 }
00927 }
00928
00929 void
00930 Patch::recompute()
00931 {
00932 if (_faces.empty()) {
00933
00934 for (int k = 0; k<_mesh->nfaces(); k++) {
00935 add(_mesh->bf(k));
00936 }
00937 }
00938 }
00939
00940 void
00941 Patch::get_faces(TAGformat &d)
00942 {
00943 ARRAY<int> faces;
00944 *d >> faces;
00945
00946
00947 for (int f = 0; f < faces.num(); f++)
00948 {
00949 if (faces[f] < _mesh->nfaces())
00950 {
00951 add(_mesh->bf(faces[f]));
00952 }
00953 else
00954 {
00955 err_msg("Patch::get_faces() - ERROR! face #%d > %d.", faces[f], _mesh->nfaces());
00956 }
00957 }
00958 }
00959
00960 void
00961 Patch::put_faces(TAGformat &d) const
00962 {
00963
00964 if (_faces.num() == ((Patch *) this)->mesh()->nfaces()) return;
00965
00966 ARRAY<int> faces(_faces.num());
00967
00968 for (int f=0; f<_faces.num(); f++)
00969 {
00970 const Bface *outf = _faces[f];
00971 if (outf->patch() != this)
00972 {
00973 err_msg("Patch::put_faces() - ERROR! face #%d has ownership issues...", outf->index());
00974 }
00975 faces += outf->index();
00976 }
00977 d.id();
00978 *d << faces;
00979 d.end_id();
00980 }
00981
00982
00983
00984 inline VEXEL
00985 cmult(CVEXEL& a, CVEXEL& b)
00986 {
00987
00988 return VEXEL(a[0]*b[0] - a[1]*b[1], a[0]*b[1] + a[1]*b[0]);
00989 }
00990 inline bool
00991 is_good(CBvert* v)
00992 {
00993 return v && v->is_front_facing() && v->wloc().in_frustum();
00994 }
00995
00996 inline double
00997 get_weight(CBvert* v)
00998 {
00999 return (!is_good(v)) ? 0 : 1.0;
01000 }
01001
01002 inline bool
01003 is_good(CBface* f, CWpt& p)
01004 {
01005
01006 return f && f->front_facing() && p.in_frustum();
01007 }
01008
01009 inline double
01010 get_weight(CBface* f, CWpt& p)
01011 {
01012 return (!is_good(f, p)) ? 0 : 1.0;
01013 }
01014
01015 inline double
01016 sum_weights(const vector<DynamicSample>& w1, const vector<DynamicSample>& w2)
01017 {
01018
01019
01020
01021 double ret = 0;
01022 for (uint i=0; i< w1.size(); ++i)
01023 if ((w1[i]).get_weight() > 0 && (w2[i]).get_weight() > 0)
01024 ret += (w1[i]).get_weight();
01025 return ret;
01026 }
01027
01028 inline PIXEL
01029 weighted_sum(const vector<DynamicSample>& w1,
01030 const vector<DynamicSample>& w2)
01031 {
01032
01033
01034
01035 assert(w1.size() == w2.size());
01036 PIXEL ret;
01037 for (uint i=0; i<w1.size(); ++i)
01038 if (w1[i].get_weight() > 0 && w2[i].get_weight() > 0)
01039 ret += w1[i].get_pix()*w1[i].get_weight();
01040 return ret;
01041 }
01042
01043 void
01044 Patch::create_dynamic_samples()
01045 {
01046 _old_samples.clear();
01047
01048 Bface_list faces;
01049 ARRAY<Wvec> bc_list;
01050
01051 generate_samples(_mesh, faces ,bc_list ,5 ,0.35 ,20);
01052
01053 assert(faces.num() == bc_list.num());
01054
01055 for(int i=0; i < faces.num(); ++i){
01056
01057
01058
01059
01060
01061
01062 Wpt pos;
01063 faces[i]->bc2pos(bc_list[i], pos);
01064 PIXEL pix = PIXEL(pos);
01065 double weight = get_weight((CBface*)faces[i], pos);
01066 DynamicSample sample(faces[i], bc_list[i], pix, weight);
01067 _old_samples.push_back(sample);
01068 }
01069 }
01070
01071 void
01072 Patch::update_dynamic_samples()
01073 {
01074 if(!_do_dynamic_stuff)
01075 return;
01076
01077 if (_dynamic_stamp == VIEW::stamp())
01078 return;
01079 _dynamic_stamp = VIEW::stamp();
01080
01081
01082
01083 VEXEL delt;
01084 delt = VEXEL(0,0);
01085 _z = VEXEL(1,0);
01086 if(_old_samples.empty())
01087 create_dynamic_samples();
01088
01089
01090 vector<DynamicSample> new_samples;
01091 for (uint i=0; i< _old_samples.size(); ++i) {
01092
01093
01094
01095
01096
01097 PIXEL pix = PIXEL(_old_samples[i].get_pos(xform()));
01098 bool weight = get_weight((CBface*)_old_samples[i].get_simplex(),
01099 _old_samples[i].get_pos(xform()));
01100 DynamicSample sample(_old_samples[i].get_simplex(),
01101 _old_samples[i].get_bc(), pix, weight);
01102 new_samples.push_back(sample);
01103 }
01104
01105
01106 assert(new_samples.size() == _old_samples.size());
01107
01108
01109
01110
01111
01112
01113 double ow = sum_weights(_old_samples, new_samples);
01114 double nw = sum_weights( new_samples, _old_samples);
01115
01116 if (ow < epsZeroMath() || nw < epsZeroMath()) {
01117
01118
01119
01120 _old_samples = new_samples;
01121
01122
01123 update_dynamic_samples();
01124
01125 return;
01126 }
01127 _old_center = weighted_sum(_old_samples, new_samples)/ow;
01128 _new_center = weighted_sum(new_samples, _old_samples)/nw;
01129
01130
01131 delt = _new_center - _old_center;
01132
01133
01134 _z = VEXEL(0,0);
01135 double so = 0;
01136 double sn = 0;
01137 for (unsigned int k=0; k< new_samples.size(); ++k) {
01138 if (new_samples[k].get_weight() > 0 && _old_samples[k].get_weight() > 0) {
01139
01140 VEXEL o = _old_samples[k].get_pix() - _old_center;
01141 VEXEL n = new_samples[k].get_pix() - _new_center;
01142
01143 double w = new_samples[k].get_weight();
01144 _z += VEXEL(o*n, det(o,n))*w;
01145 so += o.length_sqrd()*w;
01146 sn += n.length_sqrd()*w;
01147 }
01148 }
01149 if (isZero(so) || isZero(sn)) {
01150
01151 cerr << "Patch::calculate_xform: error, divide by zero "
01152 << so << " " << sn << " " << new_samples.size() <<" " << _old_samples.size() << endl;
01153 _z = VEXEL(1,0);
01154
01155
01156 return;
01157 }
01158
01159 bool do_symmetric = true;
01160 if (!do_symmetric) {
01161
01162 _z /= so;
01163 } else {
01164
01165 _z = _z.normalized() * sqrt(sn/so);
01166 }
01167
01168 _old_samples.clear();
01169 _old_samples = new_samples;
01170
01171
01172 if(_do_lod)
01173 _scale *= _z.length();
01174
01175 _o = _new_center + cmult(_o - _old_center, _z);
01176 _u_o = _new_center + cmult(_u_o - _old_center, _z);
01177 _v_o = _new_center + cmult(_v_o - _old_center, _z);
01178
01179
01180 double s = _scale;
01181 assert(s > 0);
01182
01183 while (s >= 2) s /= 2;
01184 while (s < 1) s *= 2;
01185
01186
01187 const float st0 = 1.3;
01188 const float st1 = 1.7;
01189 _lod_t = (s < st0) ? 0.0 : (s > st1) ? 1.0: (s - st0)/(st1 - st0);
01190 _lod_u = sample_u_vec().normalized()*s;
01191 _lod_v = sample_v_vec().normalized()*s;
01192
01193 if (Config::get_var_bool("DEBUG_DYN_SAMPLE_LOD",false))
01194 cerr << "s0: " << s/2 << ", s1: " << s << ", t: " << _lod_t << endl;
01195 }
01196
01197 void
01198 Patch::reset_dynamic_samples()
01199 {
01200 }
01201
01202