Friday, December 5, 2014

Ogre falloff 2 node cspline interpolation class

  #include <OgreMatrix4.h>  

 class Falloffinterpolate{
      public:
           double tparam, crfalloff, ctramount;
           Ogre::Vector3 cpoint;
           Ogre::Vector3 cipoint; //interpolated position
           Ogre::Vector3 ccpoint; //center point for falloff radii
           Ogre::Vector4 cicoeff;
           Falloffinterpolate(Ogre::Vector3 point, Ogre::Vector3 clpoint, double rfalloff, Ogre::Vector4 icoeff, double tramount);
           Falloffinterpolate(std::vector<Ogre::Vector3> falloffSelection, Ogre::Vector3 clpoint,
           double rfalloff, Ogre::Vector4 icoeff, double tramount);
           ~Falloffinterpolate(void);
           Ogre::Vector3 getIpoint(void);
           std::vector<Ogre::Vector3> getIpoints(void);
      private:
           double computetparam(void); //normalized distance measure from ccpoint to cpoint.
           Ogre::Vector3 computeinterp(void);
           std::vector<Ogre::Vector3> cfalloffSelection;
           //std::vector<Ogre::Real> Ipoints;
           std::vector<Ogre::Vector3> Ipoints;
 };
 Falloffinterpolate::Falloffinterpolate(Ogre::Vector3 point, Ogre::Vector3 clpoint, double rfalloff, Ogre::Vector4 icoeff, double tramount){
      cpoint = point;
      ccpoint = clpoint;
      cicoeff = icoeff;
      crfalloff = rfalloff;
      ctramount = tramount;
      tparam = computetparam();
      cipoint = computeinterp();
      Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
      std::ostringstream ss;
      ss<<"Faloffinterpolation********\n";
      ss<<"cpoint: "<< cpoint << "\n";
      ss<<"ccpoint: "<< ccpoint << "\n";
      ss<<"ctramount: "<< ctramount << "\n";
      tlog->logMessage(ss.str());
 }
 Falloffinterpolate::Falloffinterpolate(std::vector<Ogre::Vector3> falloffSelection, Ogre::Vector3 clpoint, double rfalloff, Ogre::Vector4 icoeff, double tramount){
      //cpoint = point;
      cfalloffSelection = falloffSelection;
      ccpoint = clpoint;
      cicoeff = icoeff;
      crfalloff = rfalloff;
      ctramount = tramount;
      Ipoints.resize(falloffSelection.size());
      std::ostringstream ss;
      for (int i = 0; i < falloffSelection.size(); i++){
           cpoint = falloffSelection[i];
           tparam = computetparam();
           cipoint = computeinterp();
           Ipoints[i] = Ogre::Vector3(cipoint.x,cipoint.y,cipoint.z);
           //ss<<"tparam: "<<tparam<<"\n";
           //ss<<"translate point: "<<cipoint.y<<"\n";
      }
      //tparam = computetparam();
      //cipoint = computeinterp();
      Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
      ss<<"Faloffinterpolation********\n";
      ss<<"cpoint: "<< cpoint << "\n";
      ss<<"ccpoint: "<< ccpoint << "\n";
      ss<<"ctramount: "<< ctramount << "\n";
      ss<<"coefficients: "<<cicoeff<<"\n";
      ss<<"compute 2^2: " << pow(-2.0,2) << "\n";
      ss<<"coefficent w: " << cicoeff.w << "\n";
      tlog->logMessage(ss.str());
 }
 Falloffinterpolate::~Falloffinterpolate(){
 }
 double Falloffinterpolate::computetparam(){
      //tparam is normalized relative crfalloff. This should be a value between 0 and 1.
      // distance measure for tparam is done on xz plane strictly...we neglect height
      //when selecting a set of vertices.
      Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
      std::ostringstream ss;
      ss << "point 1: "<< cpoint.x<<","<< cpoint.z << "\n";
      ss << "center point: "<< ccpoint.x<< ","<<ccpoint.z << "\n";
      tlog->logMessage(ss.str());
      return 1-(pow(pow(abs(cpoint.x - ccpoint.x), 2)+pow(abs(cpoint.z - ccpoint.z), 2), .5) / crfalloff);
 }
 Ogre::Vector3 Falloffinterpolate::computeinterp(){
      //f(x_i)=a+bx_i+cx_i^2+dx_i^3. is the ordering on coefficients
      //for the 2 node cspline method that we call upon.
      double x = cicoeff[0] + cicoeff[1]*abs(tparam) + cicoeff[2]*pow(tparam,2) + cicoeff[3]*pow(abs(tparam),3);
      //next we rescale this by the translation factor ctramount.
      double hpos = abs(x)*ctramount; //or height position
      //double hpos = tparam*ctramount;
      //next we translate this to the existing position and return this.
      //Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
      //std::ostringstream ss;
      //ss << "translate amount: "<< hpos << "\n";
      //tlog->logMessage(ss.str());
      return Ogre::Vector3(cpoint.x, cpoint.y+hpos, cpoint.z);
 }
 Ogre::Vector3 Falloffinterpolate::getIpoint(){
      return cipoint;
 }
 std::vector<Ogre::Vector3> Falloffinterpolate::getIpoints(){
      return Ipoints;
 }

This basically takes coefficient data, alongside selected vertices, presumed already determined as within a given fall off radius, and then position interpolates the height map data by a given translation amount for a falloff curvature type (computed with a call to the cspline class in the previous post).

Here's some instancing snippet:

                 Ogre::Vector3 trheight = planeint->getHeight();  

                Ogre::Terrain* cterrain = mTerrainGroup->getTerrain(0,0);
                cterrain->dirty();
                Ogre::Log* tlog = Ogre::LogManager::getSingleton().getLog("test.log");
                std::ostringstream ss5;
                Falloffinterpolate fint = Falloffinterpolate(falloffSelection, crlterrVectorts, falloffwidth, falloffcoeff, (double) trheight.y);
                std::vector<Ogre::Vector3> newpos1s = fint.getIpoints();
                for (int i = 0;i < falloffSelection.size();i++){
                     Ogre::Vector3 pos1 = falloffSelection[i];
                     //ss5<<"Pre Interpolated position: "<< pos1<<"\n";
 //                    Falloffinterpolate fint = Falloffinterpolate(pos1, rlterrVector, 20.0, falloffcoeff, (double) trheight.y);
 //                    Ogre::Vector3 newpos1 = fint.getIpoint();
                     //ss5<<"Interpolated position: "<< newpos1s[i] <<"\n";
                     Ogre::Vector3 outvec(0,0,0);
                     Ogre::Vector3* outvecp = &outvec;
                     //const Ogre::Vector3 invec = Ogre::Vector3(pos1.x, newpos1s[i],pos1.z);
                     //const Ogre::Vector3& invecp = &invec;
                     //cterrain->getTerrainPosition(invec,&outvec);
                     cterrain->setHeightAtPoint (newpos1s[i].x, newpos1s[i].z, newpos1s[i].y);
                }
                ss5<<"Translate Height: "<< trheight.y<<"\n";
                tlog->logMessage(ss5.str());
                ss5.str(std::string());
                cterrain->update();


I have a lot of commenting here mostly for reading test data.
the falloffSelection object above is a std::vector container containing all selected vertices given by terrain position...not world position coordinates but sort organized by world coordinate ordering and not by terrain ordering...namely Vector3(terrainspace.x, terrainspace.z, terrainspace.y) 

crlterrVectorts is the terrain space coordinate world space coordinate ordering Ogre::Vector3 object which represents the given point for terrain translation (this represents the given terrain point in which are translation fall off radii is centered for the given translation tool.

falloffwidth I have actually adapted this with OIS::KC_F1 and OIS::KC_F2 calls in this test for increment and decrement units += 10 terrainspace units.

(double) trheight.y  I have covered the mouseviewport ray plane intersection test in a previous post on how to obtain a user supplied translation height...keep in mind that I have instantiated this interpolation class in the mousemoved listener so that the user can real time change translation data (akin to blender's translation graphical functionality).

Its worth mentioning that I parameterize the distance measure of any point within the falloff selection scope by dividing the distance of such point with the center falloff by the overall fall off radius, and then I subtract this parametric quantity by 1 to invert the selection...this ensures that the center of the fall off is given to full translation while the boundaries at full fall off radii distance have zero translations, and all other points are translated according to the parametric position (between 0 and 1) of the fall off curve where those closest to the out boundary of the falloff radii are given to less translation relative to the those closest to the center.  This reflected in the parametric choice in representing such point as described above.

On a final note, I convert to terrain space avoiding world space computations for translations here since ultimately it appears the setPoint() type function for Ogre's terrain system is done in terrain space and not world space.  Thus if having worked terrain translations using World space coordinates likely I'd have much finer gradation in point translation then necessary which would ultimately be truncated in the conversion to terrain coordinate system and then using the set methods for assigning coordinate heights, or in other words, if using world space one would have likely acquired needless points to this computation.

Don't forget that when converting to terrain space coordinates (check API on this) terrain coordinates are yielded with a base vector on the x,y or corresponding x,z world space coordinate.  A base vector or otherwise synonymous in mathematics with a normalized vector, has numeric ranges between 0 and 1 where 1 represents the maximal coordinate position on the terrain, or in other words with a terrain of size 513 x 513 a base vector of coordinate (1,1) would be position (512,512) on such terrain space (not a base terrain coordinate) The set method however utilizes non base terrain coordinates so you'll need to multiply the base vector x,y terrain coordinates by the terrain size, or in the tutorial's case 513...don't multiply the height value since this remains unchanged through world space and terrain space coordinate systems..

No comments:

Post a Comment

Oblivion

 Between the fascination of an upcoming pandemic ridden college football season, Taylor Swift, and Kim Kardashian, wildfires, crazier weathe...