00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_VISX_FISH_CC_UTC20050626084016_DEFINED
00035 #define GROOVX_VISX_FISH_CC_UTC20050626084016_DEFINED
00036
00037 #include "fish.h"
00038
00039 #include "geom/rect.h"
00040 #include "geom/vec3.h"
00041
00042 #include "gfx/bbox.h"
00043 #include "gfx/canvas.h"
00044 #include "gfx/rgbacolor.h"
00045
00046 #include "io/ioproxy.h"
00047 #include "io/reader.h"
00048 #include "io/writer.h"
00049
00050 #include "nub/ref.h"
00051
00052 #include "rutz/arrays.h"
00053 #include "rutz/error.h"
00054 #include "rutz/fstring.h"
00055 #include "rutz/sfmt.h"
00056
00057 #include <fstream>
00058
00059 #define GVX_DYNAMIC_TRACE_EXPR Fish::tracer.status()
00060 #include "rutz/trace.h"
00061 #include "rutz/debug.h"
00062 GVX_DBG_REGISTER
00063
00064 using rutz::fstring;
00065
00067
00068
00069
00071
00072 namespace
00073 {
00074 int dummy_int=0;
00075
00076 const io::version_id FISH_SVID = 4;
00077
00078 using geom::vec2d;
00079 using geom::vec3f;
00080 using geom::vec3d;
00081
00082 const int DF_0 = 0;
00083 const int TF_1 = 1;
00084 const int LF_2 = 2;
00085 const int MA_3 = 3;
00086 }
00087
00088 rutz::tracer Fish::tracer;
00089
00091
00092
00093
00094
00095
00096
00097
00099
00100 struct Fish::Part
00101 {
00102 Part() :
00103 itsKnots(), itsCtrlPnts(),
00104 itsBkpt(1), itsPt0(), itsPt1(),
00105 itsCoord(0.0)
00106 {}
00107
00108 rutz::dynamic_block<float> itsKnots;
00109
00110 rutz::dynamic_block<vec3f> itsCtrlPnts;
00111
00112
00113
00114
00115
00116
00117 int itsBkpt;
00118 vec3f itsPt0;
00119 vec3f itsPt1;
00120
00121 double itsCoord;
00122
00123 template <std::size_t N1, std::size_t N2>
00124 void reset(float const (&knots)[N1], vec3f const (&points)[N2])
00125 {
00126 itsKnots.assign(rutz::array_begin(knots),
00127 rutz::array_end(knots));
00128 itsCtrlPnts.assign(rutz::array_begin(points),
00129 rutz::array_end(points));
00130 itsCoord = 0.0;
00131 }
00132 };
00133
00134
00136
00137
00138
00140
00141 const FieldMap& Fish::classFields()
00142 {
00143 static const Field FIELD_ARRAY[] =
00144 {
00145 Field("category", &Fish::itsFishCategory, 0, 0, 10, 1, Field::NEW_GROUP),
00146 Field("dorsalFinCoord", &Fish::itsDorsalFinCoord, 0.0, -2.0, 2.0, 0.1),
00147 Field("tailFinCoord", &Fish::itsTailFinCoord, 0.0, -2.0, 2.0, 0.1),
00148 Field("lowerFinCoord", &Fish::itsLowerFinCoord, 0.0, -2.0, 2.0, 0.1),
00149 Field("mouthCoord", &Fish::itsMouthCoord, 0.0, -2.0, 2.0, 0.1),
00150
00151 Field("currentPart", &Fish::itsCurrentPart, 0, 0, 3, 1,
00152 Field::NEW_GROUP | Field::CHECKED | Field::TRANSIENT),
00153
00154 Field("currentPartBkpt", &Fish::itsCurrentPartBkpt, 1, 1, 10, 1,
00155 Field::TRANSIENT),
00156
00157 Field("inColor", &Fish::inColor,
00158 false, false, true, true, Field::BOOLEAN | Field::TRANSIENT),
00159 Field("showControlPoints", &Fish::showControlPoints,
00160 false, false, true, true, Field::BOOLEAN | Field::TRANSIENT),
00161 Field("partsMask", &Fish::partsMask,
00162 0, 0, 15, 1, Field::TRANSIENT),
00163 Field("swimStroke", &Fish::swimStroke,
00164 0.0, -1.0, 1.0, 0.1, Field::TRANSIENT)
00165 };
00166
00167 static FieldMap FISH_FIELDS(FIELD_ARRAY, &GxShapeKit::classFields());
00168
00169 return FISH_FIELDS;
00170 }
00171
00172 Fish* Fish::make()
00173 {
00174 GVX_TRACE("Fish::make");
00175 return new Fish;
00176 }
00177
00178 Fish* Fish::makeFromFiles(const char* splinefile,
00179 const char* coordfile, int index)
00180 {
00181 GVX_TRACE("Fish::makeFromFiles");
00182 return new Fish(splinefile, coordfile, index);
00183 }
00184
00185 Fish::Fish(const char* splinefile, const char* coordfile, int index) :
00186 itsParts(new Fish::Part[4]),
00187 itsFishCategory(-1),
00188 itsDorsalFinCoord(&itsParts[DF_0].itsCoord),
00189 itsTailFinCoord(&itsParts[TF_1].itsCoord),
00190 itsLowerFinCoord(&itsParts[LF_2].itsCoord),
00191 itsMouthCoord(&itsParts[MA_3].itsCoord),
00192 itsCurrentPart(0),
00193 itsCurrentPartBkpt(&dummy_int),
00194 inColor(false),
00195 showControlPoints(false),
00196 partsMask(0),
00197 swimStroke(0.0)
00198 {
00199 GVX_TRACE("Fish::Fish");
00200
00201 setFieldMap(Fish::classFields());
00202
00203 if (splinefile != 0 && coordfile != 0)
00204 {
00205 readSplineFile(splinefile);
00206 readCoordFile(coordfile, index);
00207 }
00208 else
00209 {
00210 restoreToDefault();
00211 }
00212
00213 nub::floating_ref<Fish> ref(this);
00214
00215 this->sigNodeChanged.connect(this, &Fish::updatePtrs);
00216
00217 this->sigNodeChanged.emit();
00218 }
00219
00220 Fish::~Fish () throw()
00221 {
00222 GVX_TRACE("Fish::~Fish");
00223 delete [] itsParts;
00224 }
00225
00226 void Fish::restoreToDefault()
00227 {
00228 GVX_TRACE("Fish::restoreToDefault");
00229
00230 static const float knots[] =
00231 {
00232 0.0, 0.0, 0.0, 0.0,
00233 0.1667, 0.3333, 0.5000, 0.6667, 0.8333,
00234 1.0, 1.0, 1.0, 1.0
00235 };
00236
00237 static const vec3f DF_coefs[] =
00238 {
00239 vec3f(-0.2856, 0.2915, 0.2856),
00240 vec3f(-0.2140, 0.2866, 0.2140),
00241 vec3f(-0.2176, 0.2863, 0.2176),
00242 vec3f(-0.0735, 0.4670, 0.0735),
00243 vec3f( 0.0168, 0.3913, 0.0168),
00244 vec3f( 0.1101, 0.3071, 0.1101),
00245 vec3f( 0.3049, 0.1048, 0.3049),
00246 vec3f( 0.0953, 0.1800, 0.0953),
00247 vec3f( 0.1597, 0.1538, 0.1597),
00248 };
00249
00250 static const vec3f TF_coefs[] =
00251 {
00252 vec3f( 0.1597, 0.1538, 0.1597),
00253 vec3f( 0.2992, 0.1016, 0.2992),
00254 vec3f( 0.2864, 0.1044, 0.2864),
00255 vec3f( 0.7837, 0.1590, 0.7837),
00256 vec3f( 0.4247, 0.0155, 0.4247),
00257 vec3f( 0.6362, -0.3203, 0.6362),
00258 vec3f( 0.3379, -0.0706, 0.3379),
00259 vec3f( 0.3137, 0.0049, 0.3137),
00260 vec3f( 0.1573, -0.0401, 0.1573),
00261 };
00262
00263 static const vec3f LF_coefs[] =
00264 {
00265 vec3f( 0.1573, -0.0401, 0.1573),
00266 vec3f( 0.2494, -0.0294, 0.2494),
00267 vec3f( 0.1822, -0.0877, 0.1822),
00268 vec3f(-0.0208, -0.3236, 0.0208),
00269 vec3f(-0.0632, -0.3412, 0.0632),
00270 vec3f(-0.1749, -0.1120, 0.1749),
00271 vec3f(-0.1260, -0.4172, 0.1260),
00272 vec3f(-0.3242, -0.1818, 0.3242),
00273 vec3f(-0.2844, -0.1840, 0.2844),
00274 };
00275
00276 static const vec3f MA_coefs[] =
00277 {
00278 vec3f(-0.2844, -0.1840, 0.2844),
00279 vec3f(-0.3492, -0.1834, 0.3492),
00280 vec3f(-0.4554, -0.1489, 0.4554),
00281 vec3f(-0.6135, -0.0410, 0.6135),
00282 vec3f(-0.7018, 0.0346, 0.7018),
00283 vec3f(-0.5693, 0.1147, 0.5693),
00284 vec3f(-0.4507, 0.2227, 0.4507),
00285 vec3f(-0.3393, 0.2737, 0.3393),
00286 vec3f(-0.2856, 0.2915, 0.2856),
00287 };
00288
00289 itsParts[DF_0].reset(knots, DF_coefs);
00290 itsParts[TF_1].reset(knots, TF_coefs);
00291 itsParts[LF_2].reset(knots, LF_coefs);
00292 itsParts[MA_3].reset(knots, MA_coefs);
00293
00294 itsParts[DF_0].itsBkpt = 6;
00295 itsParts[DF_0].itsPt0.set(0.2380, 0.3416, 0.2380);
00296 itsParts[DF_0].itsPt1.set(-0.0236, 0.2711, 0.0236);
00297
00298 itsParts[TF_1].itsBkpt = 5;
00299 itsParts[TF_1].itsPt0.set(0.6514, -0.0305, 0.6514);
00300 itsParts[TF_1].itsPt1.set(0.2433, 0.0523, 0.2433);
00301
00302 itsParts[LF_2].itsBkpt = 6;
00303 itsParts[LF_2].itsPt0.set(-0.2121, 0.0083, 0.2121);
00304 itsParts[LF_2].itsPt1.set(-0.1192, -0.2925, 0.1192);
00305
00306 itsParts[MA_3].itsBkpt = 5;
00307 itsParts[MA_3].itsPt0.set(-0.7015, 0.1584, 0.7015);
00308 itsParts[MA_3].itsPt1.set(-0.7022, -0.1054, 0.7022);
00309 }
00310
00311 io::version_id Fish::class_version_id() const
00312 {
00313 GVX_TRACE("Fish::class_version_id");
00314 return FISH_SVID;
00315 }
00316
00317 void Fish::read_from(io::reader& reader)
00318 {
00319 GVX_TRACE("Fish::read_from");
00320
00321 reader.ensure_version_id("Fish", 4,
00322 "Try cvs tag xml_conversion_20040526",
00323 SRC_POS);
00324
00325 readFieldsFrom(reader, classFields());
00326
00327 reader.read_base_class("GxShapeKit", io::make_proxy<GxShapeKit>(this));
00328 }
00329
00330 void Fish::write_to(io::writer& writer) const
00331 {
00332 GVX_TRACE("Fish::write_to");
00333
00334 writer.ensure_output_version_id("Fish", FISH_SVID, 4,
00335 "Try groovx0.8a7", SRC_POS);
00336
00337 writeFieldsTo(writer, classFields(), FISH_SVID);
00338
00339 writer.write_base_class("GxShapeKit", io::make_const_proxy<GxShapeKit>(this));
00340 }
00341
00342 void Fish::updatePtrs()
00343 {
00344 GVX_TRACE("Fish::updatePtrs");
00345
00346 itsCurrentPartBkpt = &(itsParts[itsCurrentPart].itsBkpt);
00347 }
00348
00349 void Fish::readSplineFile(const char* splinefile)
00350 {
00351 GVX_TRACE("Fish::readSplineFile");
00352 size_t i, j;
00353 int k, splnb;
00354 fstring dummy;
00355
00356
00357 std::ifstream ifs(splinefile);
00358 if (ifs.fail())
00359 {
00360 throw rutz::error(rutz::sfmt("error opening file '%s'",
00361 splinefile), SRC_POS);
00362 }
00363
00364 for(i = 0; i < 4; ++i)
00365 {
00366 int dummy_order;
00367
00368
00369 ifs >> dummy >> splnb >> dummy >> dummy_order;
00370
00371
00372 int nknots;
00373 ifs >> dummy >> nknots;
00374
00375
00376 itsParts[i].itsKnots.resize(nknots);
00377 for (j = 0; j < itsParts[i].itsKnots.size(); ++j)
00378 {
00379 ifs >> itsParts[i].itsKnots[j];
00380 }
00381
00382
00383 int ncoefs;
00384 ifs >> dummy >> ncoefs;
00385
00386
00387 itsParts[i].itsCtrlPnts.resize(ncoefs);
00388 {
00389 for (k = 0; k < ncoefs; ++k)
00390 {
00391 ifs >> itsParts[i].itsCtrlPnts[k].x();
00392 }
00393 }
00394 {
00395 for (k = 0; k < ncoefs; ++k)
00396 {
00397 ifs >> itsParts[i].itsCtrlPnts[k].y();
00398 }
00399 }
00400 {
00401 for (k = 0; k < ncoefs; ++k)
00402 {
00403 itsParts[i].itsCtrlPnts[k].z() = 0.0;
00404 }
00405 }
00406
00407 if (ifs.fail())
00408 {
00409 throw rutz::error(rutz::sfmt("error reading file '%s'",
00410 splinefile), SRC_POS);
00411 }
00412 }
00413
00414
00415 for(i = 0; i < 4; ++i)
00416 {
00417 int which = 0;
00418
00419 int endptnb = 0;
00420
00421
00422 ifs >> dummy >> endptnb
00423 >> dummy >> which
00424 >> dummy >> itsParts[(which-1)].itsBkpt;
00425
00426 if (which <= 0)
00427 {
00428 throw rutz::error(rutz::sfmt("bad 'which' value '%d' while "
00429 "reading fish coords", which),
00430 SRC_POS);
00431 }
00432
00433
00434 ifs >> dummy >> dummy;
00435
00436
00437 ifs >> itsParts[(which-1)].itsPt0.x() >> itsParts[(which-1)].itsPt1.x()
00438 >> itsParts[(which-1)].itsPt0.y() >> itsParts[(which-1)].itsPt1.y();
00439
00440 if (ifs.fail())
00441 {
00442 throw rutz::error(rutz::sfmt("error reading file '%s'",
00443 splinefile), SRC_POS);
00444 }
00445 }
00446 }
00447
00448 void Fish::readCoordFile(const char* coordfile, int index)
00449 {
00450 GVX_TRACE("Fish::readCoordFile");
00451 fstring dummy;
00452
00453 std::ifstream ifs(coordfile);
00454 if (ifs.fail())
00455 {
00456 throw rutz::error(rutz::sfmt("error opening file '%s'",
00457 coordfile), SRC_POS);
00458 }
00459
00460
00461 for (int j = 0; j < index-1; ++j)
00462 {
00463 getline(ifs, dummy, '\n');
00464 }
00465
00466 ifs >> itsFishCategory;
00467
00468 for (int i = 0; i < 4; ++i)
00469 {
00470 ifs >> itsParts[i].itsCoord;
00471 }
00472
00473 if (ifs.fail())
00474 {
00475 throw rutz::error(rutz::sfmt("error reading file '%s'",
00476 coordfile), SRC_POS);
00477 }
00478 }
00479
00480 void Fish::grGetBoundingBox(Gfx::Bbox& bbox) const
00481 {
00482 GVX_TRACE("Fish::grGetBoundingBox");
00483
00484 bbox.vertex2(vec2d(-0.75, -0.5));
00485 bbox.vertex2(vec2d(+0.75, +0.5));
00486 }
00487
00488 void Fish::grRender(Gfx::Canvas& canvas) const
00489 {
00490 GVX_TRACE("Fish::grRender");
00491
00492 static Gfx::RgbaColor colors[4] =
00493 {
00494 Gfx::RgbaColor(1.0, 0.0, 0.0, 1.0),
00495 Gfx::RgbaColor(0.0, 1.0, 0.0, 1.0),
00496 Gfx::RgbaColor(0.0, 0.0, 1.0, 1.0),
00497 Gfx::RgbaColor(0.0, 0.0, 0.0, 1.0)
00498 };
00499
00500
00501 for (int i = 0; i < 4; ++i)
00502 {
00503 if ((1 << i) & partsMask)
00504 continue;
00505
00506 if (inColor)
00507 canvas.setColor(colors[i]);
00508
00509 rutz::dynamic_block<vec3f> ctrlpnts(itsParts[i].itsCtrlPnts);
00510
00511
00512
00513
00514 float alpha = 0.5*(1-itsParts[i].itsCoord);
00515 float beta = 0.5*(1+itsParts[i].itsCoord);
00516
00517 vec3f pt = itsParts[i].itsPt0 * alpha + itsParts[i].itsPt1 * beta;
00518
00519
00520 unsigned int bkpt = itsParts[i].itsBkpt - 1;
00521
00522 if (bkpt < ctrlpnts.size())
00523 ctrlpnts[bkpt] = pt;
00524
00525 for (unsigned int j = 0; j < ctrlpnts.size(); ++j)
00526 {
00527 ctrlpnts[j].z() =
00528 ctrlpnts[j].z() * ctrlpnts[j].z() * swimStroke;
00529 }
00530
00531 canvas.drawNurbsCurve(itsParts[i].itsKnots, ctrlpnts);
00532
00533 if (showControlPoints)
00534 {
00535 if (0)
00536 {
00537
00538
00539
00540
00541
00542
00543 Gfx::AttribSaver saver(canvas);
00544 canvas.setPointSize(4.0);
00545
00546 Gfx::PointsBlock block(canvas);
00547 for (unsigned int i = 0; i < ctrlpnts.size(); ++i)
00548 {
00549 canvas.vertex3(vec3d(ctrlpnts[i]));
00550 }
00551 }
00552 else
00553 {
00554 Gfx::AttribSaver saver(canvas);
00555 canvas.setPolygonFill(true);
00556 geom::rect<double> rect;
00557 for (unsigned int i = 0; i < ctrlpnts.size(); ++i)
00558 {
00559 Gfx::MatrixSaver msaver(canvas);
00560 canvas.translate(vec3d(0.0, 0.0, ctrlpnts[i].z()));
00561 rect.set_lbwh(ctrlpnts[i].x(), ctrlpnts[i].y(),
00562 0.03, 0.03);
00563 canvas.drawRect(rect);
00564 }
00565 }
00566 {
00567 Gfx::LinesBlock block(canvas);
00568 canvas.vertex2(vec2d(itsParts[i].itsPt0.as_vec2()));
00569 canvas.vertex2(vec2d(itsParts[i].itsPt1.as_vec2()));
00570 }
00571 }
00572 }
00573 }
00574
00575
00576 static const char __attribute__((used)) vcid_groovx_visx_fish_cc_utc20050626084016[] = "$Id: fish.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00577 #endif // !GROOVX_VISX_FISH_CC_UTC20050626084016_DEFINED