fish.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 1999-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Wed Sep 29 11:44:57 1999
00010 // commit: $Id: fish.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/visx/fish.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
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 // File scope data
00069 //
00071 
00072 namespace
00073 {
00074   int dummy_int=0; // We need a dummy int to attach various CPtrField's
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 // Fish::Part struct --
00093 //
00094 // Describes one of the part of the fish (upper fin, tail, bottom fin
00095 // or mouth) as a NURBS curves, with a knot sequence and a set of
00096 // control points.
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   // -- end points --
00113 
00114   // Each endpoint is associated with a breakpoint. This is described
00115   // in this structure as well as the x and y coordinates of the two
00116   // points which define the boundaries of the endpoint line
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 // Fish member definitions
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   // read in the spline knots and coefficient
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       // spline number and order
00369       ifs >> dummy >> splnb >> dummy >> dummy_order;
00370 
00371       // number of knots
00372       int nknots;
00373       ifs >> dummy >> nknots;
00374 
00375       // allocate space and read in the successive knots
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       // number of coefficients
00383       int ncoefs;
00384       ifs >> dummy >> ncoefs;
00385 
00386       // allocate space and read in the successive coefficients
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       // endpt number, associated part and breakpoint
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       // skip the next line
00434       ifs >> dummy >> dummy;
00435 
00436       // x&y coordinates
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   // Skip (index-1) lines
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   // Loop over fish parts
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       // Set the coefficients at the break point to a linear sum of
00512       // the two corresponding endpoints
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       // indexing in the coefs array starts at 0
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               // This version (using GL_POINTS) doesn't seem to work
00538               // properly with Mesa under Linux; the problem is that
00539               // setPointSize() (i.e. glPointSize()) doesn't actually
00540               // change the size of the points that get drawn... they all
00541               // end up at 1 pixel... instead we can draw the points as
00542               // filled rects.
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

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:42 2008 by Doxygen version 1.5.5.