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..

Thursday, December 4, 2014

An Ogre Cspline class that I created for 2 node c spline computations

 #include <vector>  

 #include <OgreMatrix4.h>
 #include <OgreVector4.h>
 using namespace std;
      class cspline
      {  
        public:
           vector<double> xc;
           vector<double> yc;
           vector<double> ypc; //y prime boundary conditions
           //var Coeff =Ogre::Matrix4.Build(4,4);
           cspline (vector<double> x, vector<double> y);
           cspline (vector<double> x, vector<double> y, vector<double> yp);
           Ogre::Vector4 compute2nodecspline (double bc1, double bc2);
           vector<Ogre::Vector4> computecspline (void);
           vector<Ogre::Vector4> computecsplinebcs (void);
           Ogre::Matrix4 coeffmatrix(double x1, double x2, double y1, double y2);
           Ogre::Matrix4 coeffmatrixi(int iter1);
           Ogre::Vector4 simplesfuncvector(int iter1,int iter2, double bc1, double bc2);
           Ogre::Vector4 splinefuncvector(int iter1,int iter2);
           Ogre::Vector4 csplinecoeff(Ogre::Matrix4 M, Ogre::Vector4 y);
           vector<double> computeslope(int iter1, int iter2);
      };
           cspline::cspline (vector<double> x, vector<double> y)
           {    
 /*    
                     if (x.Length != y.Length)
                     {
                          throw new ArgumentException ("Vectors are not the same length!");
                     }
                     if (x.Length < 2)
                     {
                          throw new ArgumentException ("vector array needs to be of length greater than 1!");
                     }
 */                    
                     //xc[sizeof(x)];
                     //yc[sizeof(y)];
                      //std::copy(std::begin(x), std::end(x), std::begin(xc));
                     //std::copy(std::begin(y), std::end(y), std::begin(yc));
                     xc=x;
                     yc=y;
           }
           cspline::cspline (vector<double> x, vector<double> y, vector<double> yp)
           {          
 /*
                if (x.Length != y.Length || x.Length != yp.Length)
                {
                     throw new ArgumentException ("Vectors are not the same length!");
                }
                if (x.Length < 2)
                {
                     throw new ArgumentException ("vector array needs to be of length greater than 1!");
                }
 */
                //copy(std::begin(x), std::end(x), std::begin(xc));
                //copy(std::begin(y), std::end(y), std::begin(yc));
                //copy(std::begin(yp),std::end(yp),std::begin(ypc));
                xc=x;
                yc=y;
                ypc=yp;
           }
           Ogre::Vector4 cspline::compute2nodecspline (double bc1, double bc2){
                //Ogre::Vector4 vcont = Ogre::Vector4.Build.Dense (2);
                Ogre::Vector4 x = Ogre::Vector4(0,0,0,0);
                for (int i=0; i< sizeof(xc); i++) {
                     if (i <sizeof(xc)-1){
                          Ogre::Matrix4 M = coeffmatrix (xc[i],xc[i+1],yc[i],yc[i+1]);
                          //Ogre::Vector4 y = splinefuncvector(i,i+1);
                          Ogre::Vector4 y = simplesfuncvector(i,i+1,bc1, bc2);
                          Ogre::Vector4 x = csplinecoeff(M,y);
                          return x;
                          //vcont = x;
                     }
                }
                return x;
           }
           vector<Ogre::Vector4> cspline::computecspline (){
                //I compute first derviative boundary conditions. You can modify this code for second or third
                //derivative boundary conditions, but would have to supply your methods for computing second
                //or third derivatives on your own, likewise, you'd need to make adjustment to the coefficient
                //matrix according to the solution method indicated below...that is, with higher order derivatives
                //adjusting the matrix with zeros and appropriate derivative order on the interpolating row equation
                //f(x_i)=a+bx_i+cx_i^2+dx_i^3.
                //int iter1 = 0;
                vector<Ogre::Vector4> vcont(sizeof(xc));
                for (int i=0; i< sizeof(xc); i++) {
                     if (i <sizeof(xc)-1){
                          Ogre::Matrix4 M = coeffmatrixi (i);
                          Ogre::Vector4 y = splinefuncvector(i,i+1);
                          Ogre::Vector4 x = csplinecoeff(M,y);
                          vcont[i] = x;
                     }
                }
                return vcont;
           }
           vector<Ogre::Vector4> cspline::computecsplinebcs (){
                // First derviative boundary conditions supplied and assumed provided with constructor.
                //You can modify this code for second or third
                //derivative boundary conditions, but would have to supply your methods for computing second
                //or third derivatives on your own, likewise, you'd need to make adjustment to the coefficient
                //matrix according to the solution method indicated below...that is, with higher order derivatives
                //adjusting the matrix with zeros and appropriate derivative order on the interpolating row equation
                //f(x_i)=a+bx_i+cx_i^2+dx_i^3.
                //int iter1 = 0;
                vector<Ogre::Vector4> vcont(sizeof(xc));
                for (int i=0; i< sizeof(xc); i++) {
                     if (i <sizeof(xc)-1){
                          Ogre::Matrix4 M = coeffmatrixi (i);
                          //Ogre::Vector4 y = splinefuncvector(i,i+1);
                          Ogre::Vector4 y = simplesfuncvector(i,i+1, ypc[i], ypc[i+1]);
                          Ogre::Vector4 x = csplinecoeff(M,y);
                          vcont[i] = x;
                     }
                }
                return vcont;
           }
           Ogre::Matrix4 cspline::coeffmatrix(double x1, double x2, double y1, double y2)
           {    
                //coefficients are determined for the cubic equation of the following order
                // f(x)= a + bx + cx^2+dx^3 and f'(x)=0+b+2cx+3dx^2
                // where f(x_i)=a+bx_i+cx_i^2+dx_i^3 and f'(x_i)=a*0+b+2cx_i+3dx_i^2 determine the rows of the
                //coefficient matrix of the spline interpolation matrix between node points.
                double coeffvals[4][4];
                for (int i=0; i < 2; i++) {
                     //double[] coeffrow= new double[4];
                     for (int j=0; j < 4;j++){
                          coeffvals[i][j]=pow(xc[i],j);
                          //Console.WriteLine (coeffvals[i,j]);
                     }
                     //coeffvals[i,j]=coeffrow;
                }
                for (int k=0; k < 2; k++) {
                     //double[] coeffrow= new double[4];
                     //Console.WriteLine (i);
                     for (int l=0; l < 4;l++){
                          if (l==0){
                               coeffvals[k+2][l]=0;
                          }
                          else {
                               coeffvals[k+2][l]= l*pow(xc[k],l-1);
                          }
                     }
                     //coeffvals[i]=coeffrow;
                }
                Ogre::Matrix4 M = Ogre::Matrix4(coeffvals[0][0], coeffvals[0][1], coeffvals[0][2],coeffvals[0][3],
                                    coeffvals[1][0],coeffvals[1][1],coeffvals[1][2],coeffvals[1][3],
                                    coeffvals[2][0],coeffvals[2][1],coeffvals[2][2],coeffvals[2][3],
                                    coeffvals[3][0],coeffvals[3][1],coeffvals[3][2],coeffvals[3][3]);
                return M;
           }
           Ogre::Matrix4 cspline::coeffmatrixi(int iter1)
           {    
                //coefficients are determined for the cubic equation of the following order
                // f(x)= a + bx + cx^2+dx^3 and f'(x)=0+b+2cx+3dx^2
                // where f(x_i)=a+bx_i+cx_i^2+dx_i^3 and f'(x_i)=a*0+b+2cx_i+3dx_i^2 determine the rows of the
                //coefficient matrix of the spline interpolation matrix between node points.
                double coeffvals[4][4];
                for (int i=0; i < 2; i++) {
                     //double[] coeffrow= new double[4];
                     for (int j=0; j < 4;j++){
                          coeffvals[i][j]=pow(xc[iter1+i],j);
                          //Console.WriteLine (coeffvals[i,j]);
                     }
                     //coeffvals[i,j]=coeffrow;
                }
                for (int k=0; k < 2; k++) {
                     //double[] coeffrow= new double[4];
                     //Console.WriteLine (i);
                     for (int l=0; l < 4;l++){
                          if (l==0){
                               coeffvals[k+2][l]=0;
                          }
                          else {
                               coeffvals[k+2][l]= l*pow(xc[iter1+k],l-1);
                          }
                     }
                     //coeffvals[i]=coeffrow;
                }
                Ogre::Matrix4 M = Ogre::Matrix4(coeffvals[0][0], coeffvals[0][1], coeffvals[0][2],coeffvals[0][3],
                                    coeffvals[1][0],coeffvals[1][1],coeffvals[1][2],coeffvals[1][3],
                                    coeffvals[2][0],coeffvals[2][1],coeffvals[2][2],coeffvals[2][3],
                                    coeffvals[3][0],coeffvals[3][1],coeffvals[3][2],coeffvals[3][3]);
                return M;
           }
           Ogre::Vector4 cspline::simplesfuncvector(int iter1,int iter2, double bc1, double bc2){
                //with supplied boundary conditions on a 2 node set
                double rvec[4];
                rvec [0] = yc [iter1];
                rvec [1] = yc [iter2];
                //double[] slopes = computeslope (iter1, iter2);
                rvec [2] = bc1;
                rvec [3] = bc2;
                Ogre::Vector4 V = Ogre::Vector4(rvec[0],rvec[1],rvec[2],rvec[3]);
                return V;
           }
           Ogre::Vector4 cspline::splinefuncvector(int iter1,int iter2){
                double rvec[4];
                rvec [0] = yc [iter1];
                rvec [1] = yc [iter2];
                vector<double> slopes = computeslope (iter1, iter2);
                rvec [2] = slopes [0];
                rvec [3] = slopes [1];
                //Ogre::Vector4 V = DenseVector.OfArray(rvec);
                Ogre::Vector4 V = Ogre::Vector4(rvec[0],rvec[1],rvec[2],rvec[3]);
                return V;
           }
           Ogre::Vector4 cspline::csplinecoeff(Ogre::Matrix4 M, Ogre::Vector4 y){
                Ogre::Matrix4 invmatrix = M.inverse();
                for (int i = 0; i < 4; i++){
                     for(int j =0; j < 4; j++){
                          if (abs(invmatrix[i][j])<1e-6){
                               invmatrix[i][j] = 0;
                          }
                     }
                }
                Ogre::Vector4 x = invmatrix*y;
                return x;
           }
           vector<double> cspline::computeslope(int iter1, int iter2){
                //computing boundary condition first dervative slope conditions. This is an average slope approaching from
                // an exterior point...that is not from (y2-y1)/(x2-x1) but a previous iteration point
                //first we check to see if the point is on our node boundary of points, if so we assign a slope of zero
                double slope1;
                double slope2;
                vector<double> slopes(2);
                if (iter1 == 0) {
                     slope1 = 0.0;
                }
                else
                {
                     slope1 = (yc[iter1]-yc[iter1-1])/(xc[iter1]-xc[iter1-1]);
                }
                if (iter2 == sizeof(xc)-1) {
                     slope2 = 0.0;
                }
                else
                {
                     slope2 = (-yc[iter2]+yc[iter2+1])/(-xc[iter1]+xc[iter1+1]);
                }
                slopes [0] = slope1;
                slopes [1] = slope2;
                return slopes;
           }
*************************************


Here's an example Ogre based instancing of the class

   cspline* cs = new cspline(twopoints,twopoints);  
    std::vector twopoints(2);
    twopoints[0] = 0;
    twopoints[1] = 1;
   double tan1 = (double)Ogre::Math::Tan(Ogre::Math::DegreesToRadians(30));
   falloffcoeff = cs->compute2nodecspline (tan1, tan1);

I haven't tested this in the generalized n node computation case, but program gives an idea as to how this is done.

Basically two boundary conditions are supplied which in this case are first order derivatives, or slopes at either point (0,0) and (1,1).

I use an array style call by the way to Ogre::Vector4 containers since Vector4.w,...,Vector.z
ordering is not alphabetically speaking similar by order principle in other words Vector4.w is mapped to Vector4[3].

By the way for the given boundary conditions supplied this yields the following equation

0.57735x +1.26795x^2-0.845299x^3 from 0 to 1

or


for the given falloff plot.

As indicated in the notes for computing coefficients in the class.  The coefficients are given by the following ordering

where cfvect is the Ogre::Vector4 coefficient vector from the cspline class

means the cubic equation would have the following form

f(x) = cfvect[0] + cfvect[1]*x +cfvect[2]*x^2+cfvect[3]*x^3

I always recommend testing a cubic equation for the desired parameters.  If you hadn't readily had online mathematical plotting software or something in Ogre immediately handy for doing this.  Wolfram Alpha provides free online software for checking a plot.

I'd mention you can instance your cspline falloff computations on the build scene method or somewhere at the program's outset, but you wouldn't need to re compute since the curve is fixed and that we parameterize/rescale the distance metric for all selected vertices.  In fact, you can likely build a library of fall off curves that can be referenced in the interpolating class method call, you just need to supply the appropriate curve coefficients from such pre compiled library. 

A quick Ogre C++ API reading translation tip if you are a noob

http://www.ogre3d.org/docs/api/1.9/

So if you were wanting to understand reading a C++ api and understanding how to invoke say class method calls say from class pointer objects or class objects, I'll provide a little reading translation help here.

Firstly in C++ if you weren't already familiarized relative other Object oriented programming languages you'd notice the '->' being featured for method calls.   Obviously you learn after the first or second crash day of C++ that this '->' call is like the '.' call for invoking a call to class method or in particular a class pointer object.  Thus if having instantiated a class pointer object say

Ogre::TerrainGroup* mTerrainGroup;

Where Ogre::TerrainGroup* is a pointer object to Ogre::TerrainGroup

Anytime a pointer object is instantiated class pointer object invocations are done with '->' as opposed to '.'
Otherwise if it were possible to declare and instantiate

Ogre::TerrainGroup mTerrainGroup;

where mTerrainGroup were a Ogre::TerrainGroup object we'd use a '.' after such object in referencing its method/function call.

Often times when referencing say the Ogre API for methods of a given class object, we can see the method call given in a given addressing format...

thus

void Ogre::Terrain::getPoint ( long  x,
long  y,
Vector3 outpos 
) const

the first token 'void' is the return type of the function call here.

the second and third token bridged by '::' references the Ogre addressing namespace alongside the class object type which is a 'Terrain' object.  Often times when you are declaring a new Ogre object, you'd typically have some referencing like 'Ogre::ogre_object_name    yourobjnamehere;'

Sometimes you'll see return types other than 'void' as indicated above returned where you can store such return object and neither having to supply some output object (in the above case it is a 'Ogre::Vector3*'  object that is required so that the method can provide a given point output to this object).

The fourth token 'getPoint' is the method name of the 'Ogre::Terrain' object...
according to ordering principles, you'd likely find method names are always delimited to the right by the '(' parentheses token.

Returning back to the example above, also if I have a given Ogre::Terrain object instantiated or a object pointer then I can reference method calls to such object by using the '.' or '->' followed by the method name

thus an object

Ogre::Terrain cterrain;
Ogre::Vector3 outputvec;

would have a method call to getPoint() as

cterrain.getPoint(0,0,&outputvec);

or

Ogre::Terrain* cterrain;
Ogre::Vector3 outputvec;
as

cterrain->getPoint(0,0,&outputvec);

Another common feature found are overloaded constructors for a given object, read through these since there may be many different ways to instantiate a given Ogre object using any variation of Ogre objects or whatever necessary to instantiate the given object.  Basically if you weren't familiar with overloading, overloading say could be as simple as allowing you to do addition on two number objects say even if they were floats or doubles, Ogre::Real and so forth so that you hadn't need worry about having a specific object type to instantiate or invoke the class object or method, or in other words less work tracking and type cast converting an object from one type to another in order to instantiate a given object type (through object constructor overloading).  Another example, An Ogre::Vector has 6 different instantiation constructors, or there are six different ways to declare and instance an Ogre::Vector (outside of pointers and anything else).

Also read through required supplied parameters/objects required to get an object up and running or invoking a given object method.

I always recommend a thorough reading of any API concerning a given Object type since outside of code recipes since this can give you a more thorough working knowledge on implementing structures or using fully the tools that such object provides so that you hadn't need do added legwork either re inventing structures by added work or anything else.




Code excerpt for updating Ogre terrain height positions and some added notes

   Ogre::Terrain* cterrain = mTerrainGroup->getTerrain(0,0);  
   ss5<<"Terrain Size: "<< cterrain->getSize()<<"\n";  
   ss5<<"Maximum Height: "<< cterrain->getMaxHeight()<<"\n";  
   ss5<<"World Size: " << cterrain->getWorldSize()<<"\n";  
   for (int i=0; i<250; i++ ){  
      for (int j=0; j<250; j++){  
        ss5 << "Terrain position("<<i<<","<<j<<")"<<cterrain->getHeightAtPoint(i,j)<<"\n" ;  
        cterrain->setHeightAtPoint(i,j,cterrain->getHeightAtPoint(i,j)+100);  
      }  
   }  
   cterrain->update();  

The above is a code snippet for updating terrain height coordinates in Ogre 1.9x using Ogre's Terrain manager system.

Some bit of things to keep in mind with Ogre's terrain system is that like Unity and I imagine other game engine's there are two separate coordinate systems namely:  world coordinate system, and local terrain coordinates.  A given tutorial for instance through Ogre Tutorial's typically load the terrain with a world coordinate dimension ranges of 12,000 x 12000 while local terrain coordinate dimension's are 513 x 513.   As related to my previous post on the subject of extracting a terrain world coordinate position from a given ray trace query, you'd want to keep in mind converting from a world coordinate to local terrain coordinate position.   Ogre provides a function to do this

void Ogre::Terrain::getTerrainPosition ( const Vector3 WSpos,
Vector3 outTSpos 
) const


or practice example

                     Ogre::Vector3 outvec(0,0,0);  

                     Ogre::Vector3* outvecp = &outvec;
                     const Ogre::Vector3 invec = Ogre::Vector3(pos1.x,pos1.z, newpos1s[i]);
                     //const Ogre::Vector3& invecp = &invec;
                     cterrain->getTerrainPosition(invec,&outvec);

Wednesday, December 3, 2014

Ogre: Notes on building a Terrain Raise/Lower Tool for a terrain tool editor

The idea pretty much while extending from some previously mentioned posts on mathematics concerning things like building a falloff for the tool in terms of raising or lowering a given terrain (see the example for computing 2 node cubic spline coefficients in a previous blog post of mine as of not too long ago).  It appears that basic and intermediate ogre tutorials provide an excellent foundation for a project such as this.  Ogre does also provide some simple interpolating smoothing functions as well, although I am not sure that you could amply customize this relative to other known methods such as the one that I've mentioned, so likely you may want to adapt (as I have done) from another game engine a given package or find a working package for c++ that does this bit math work.  Actually Ogre does provide some basic linear algebra functionality as well to do computations...for instance, Ogre::Matrix4, Ogre::Matrix3 and so forth coupled with Ogre::Vector4, and so forth which can be used for Matrix and vector products, or computing the .inverse() of a given matrix.

Adaptation legwork generally comes in the form of the design of the selection tool.  For instance, in my case, I decided to use from a given a ray to terrain intercepted point, a bounding of box of dimension 2 * radius on both sides (a square) and then from the bounding planar square, iterate the set of points inside this in determining for a given bounding geometry (in my case a circle) all the points falling inside the given tools falloff radius or 1/2 the length of the square where such points given from the distance of the center of the square are less than such fall off radius.  By using a bounding square (box) or geometry, obviously this avoids needless computations through point sets that would certainly fail otherwise.  Another selection method adapts intermediate tutorial 4, where one creates a bounding volume and then determines the points of intersections using this (likely one would need to manually handle the actual ray bounding volume query process (if using Ogre 1.9) since WorldTerrainFragments appears to be non functioning for terrain ray query processes. Unfortunately, this also still remains a little bit of greek for me, so I wouldn't be able to describe how methods would be drawn up in detail on this method especially in the way of bounding volumes.

Once having the selected vertices.  Two possibilities that I have constructed for such tool, or user configured settings terrain height translation (say, where the user can set the tool to increment with each mouse click in increments either raising or lowering such), or alternately a different method, which approximates other 3d modelers which is allowing the user to while holding the mouse button down control the rate of translation vertically all in one shot until the user depresses the mouse button key.    Again for translating points (as adapted from another blog post of mine on this subject matter), one can with a fixed falloff type pre compute on scene loading or at any time when the falloff type is selected pre compute say cspline coefficients between a normalized point set (something like points (0,0) and (1,1)) and then simply normalize the t distance parameter for such point in the given translation fall off range.  Normalizing I've found is pretty simple which is to say computing the distance between the two points and then dividing by the overall fall off radii...if you need to invert the normal t parameter you can simply use tparam* = 1-t param so that the center points is actually given to a t param* value of 1 and vice versa the most distant points are at zero (indicate no translated change in elevation at this point).  Once having the t param or t param * value then one need simply compute the corresponding fall off position using the cspline coefficient equation, and then having applied a translation scale factor or the amount that a user has selected by raising the elevation of the mouse in a given viewport.

This raises the last remaining obstacle to the problem considered here.  Since finding the view port elevation coordinates is another mathematical problem.  One could simply grab mouse coordinates but the problem obviously with this is if say grabbing the viewport to mouse pointer ray means that choosing the origin of the ray means that elevation control isn't exactly aligned say to a locked ray intercept position on such terrain, and then finessing the terrain with the mouse cursor active for terrain translation is definitely more cumbersome without projecting the position of the cursor so that it is more finely tuned to a given selected terrain position and all surrounding points.

My thought solution (not implemented as of yet), however, considers this problem by creating a perpendicular plane relative to the camera's active viewport that changes even if the viewport changes orientation relative to a terrain locked coordinate.  In this case, we can actually use the original mouse ray and from this select the ray's direction to be of aid here, and from this creating a perpendicular to viewport bounding plane that passes through the locked coordinate terrain point.

So I believe in finishing this problem, one should make use of the coordinate point, and from this take the original viewport ray's direction and rotate this as desired by 90 degrees...a  the viewport ray direction I believe is given by a three tuple vector coordinate values , construct a ray from say the locked terrain position (as the ray's origin) and then advance it, arbitrarily as desired in finding another point, or alternately you can setup the math computations (say trig or something else if desired).  Another point can similarly be yielded using an alternate 90 degree rotation on the desired coordinate axis from such direction vector with a rotation.  Ogre provides as with a lot of game programming interfaces Quaternion computations, or handy way of performing rotations Quaternion algebra (product of rotations here), and then converting this rotation back into a direction vector.

Here's another simple code recipe:

PlaneIntersection::PlaneIntersection(Ogre::Vector3 pos, Ogre::Ray mouseRay){
//Ogre::Ray topLeft = mCamera->getCameraToViewportRay(left, top);
Ogre::Vector3 dirvec = mouseRay.getDirection();
//could use quarternions, but we can get orthogonal vectors, assuming
// local x is in the direction of such vector
// that a z rotation (2d) and a y rotation should yield orthogonal
//vector components.
Ogre::Real sinsq = Ogre::Math::Sin(Ogre::Math::DegreesToRadians(90));
Ogre::Real cossq = Ogre::Math::Cos(Ogre::Math::DegreesToRadians(90));
//Ry = {{cost,0,sint},{0,1,0},{-sint,0,cost}}
Ogre::Matrix3 Roty = Ogre::Matrix3(cossq,0,sinsq,0,1,0,-1*sinsq,0,cossq);
//Rz = {{cost,-sint,0},{sint,cost,0},{0,0,1}}
Ogre::Matrix3 Rotz = Ogre::Matrix3(cossq,-1*sinsq,0,sinsq,cossq,0,0,0,1);
Ogre::Vector3 dirvecy = Roty*dirvec;  //rotated on y axis
Ogre::Vector3 dirvecz = Rotz*dirvec;  //rotated on z axis
Ogre::Ray rayy = Ogre::Ray(pos,dirvecy);
Ogre::Ray rayz = Ogre::Ray(pos,dirvecz);
Ogre::Vector3 point2 = rayy.getPoint(3);
Ogre::Vector3 point3 = rayz.getPoint(3);

Ogre::Plane tplane = Ogre::Plane(pos, point2, point3);         // front plane
std::pair test = mouseRay.intersects(tplane);
std::ostringstream ss;
ctest = test.first;
if (test.first){
ss<<"Distance to intersection: "< Ogre::Real tdist = test.second;
Ogre::Vector3 theight = mouseRay.getPoint(tdist);
cheight = theight;

}

In this case I supplied rotation matrices to a given direction vector, which provided new orthogonal direction vectors in two directions which allow for the construction of a plane that intersects the fixed raise terrain selection point and points from a given arbitrary ray cast in two different orthogonal directions relative to the originating view port mouse ray.  In this way the added points aid in constructing a plane which is parallel to the viewport and intersects the desired fixed position.

Sunday, November 30, 2014

To a family potentially dealing with duress...



Not that you may have likely been advised, but media at times can be shark infested waters where on any given days the level of lies are at an absolute atrocious level, or as in the words of another prominent woman politician that I don't particularly care for, 'Sometimes you have to have the hide of a rhino.'

If you fall on the bad side of opinions, one might add given any level of populist hype, it seems could be likened to trying to climb the rope away from the flame thrower at the monster truck rally event.  Exaggerations, distortions, character assassination, and so forth...I've dealt with it personally sometime past, and generally while things are bit more quiet these day personally speaking relative to the past, generally I've been left socially isolated.  Things quiet down generally in time, or as I like to think by way of analogy, once supposedly having been 'served', one gets back to existence.  This often deals a rethinking about people I might add.

Pray all is well there for your family.  

When you live in the United States its rarer hearing the word American dissident or dissidents, but they do exist.


Wednesday, November 26, 2014

Untitled

   

How to approach this subject if not waiting for any number of years, and likely if saying it, whether it were one of any countless numbers in saying or not saying from a given experience.

How easy is it to stray into redundancies?  How easy it to relate a common experience that others would find in disparaging terms, or so often speaking of a common issue, and this leading to a series of strikes in comment.  At this point, humorously I think I may have spent the better part of some ten minutes, writing while framing the construction of an idea, but feeling my way around the idea that I would intend in framing, an emotional plea, conveying an experience.  In such defensive posture, for it seems this way in some manner of honesty, maybe there is too much of a barrier in the posture itself, that is without outright saying it, as is common by some affectation, some convention which prevents one from saying so.

Experience and social isolation

If there is abject honesty again, it is in the degree of sincerity in saying so.  I am not certain that there is exactly loneliness in writing, at least for me.  At least given to some active cognition, is active enough, in the process of constant revisions, and to this degree, when constructing some meaning, if ever apparently given and seemingly lost, returning back and then relating.  Not to say with some inset experience that ever a form of digress hadn't existed, and that following clarity weren't an issue.   I think intention if it is considered to the idea of an allowed freedom, at times, isn't so much constructed to the sense of writing with the expressed sense of selling anything, or conveying an idea that is exactly one felt out by some reader in the clearer sense.  At least imagining, in such freedom, should mean imagining without the clearest sense of empirical derivation to the degree of one writing.  That is, having spoken and spoken to others, testing self born or derived ideas by others.  Not haphazard, although one might see such a creative process as haphazard, and in this way I relate what it is that an individuality does in the process of an independence in doing so.  Testing ideas by others, is one given to the likely condition that were more or less communed upon, the idea of sharing an idea with others or that in such a craft arose, for instance, a character from a novel, an idea that weren't born in a vacuum, or at least as obviously stated, that ever any experience should have vacuous origins.  Here I am led to reconsider that an assertion weren't readily tested by way of some logical contradiction, some thought example, for instance, that contradicts a given claim, however often one might be engaged in the process of doing so repeatedly.  As given likely this sort of free form testing, as one should imagine, is like a right brain constantly being tested by a left brain, and existential construction is left somewhere in a middle region, a given compromise of sorts in the active consideration of thoughts.  I am not certain to revise the header, even if it hadn't seemed as obviously clear, but that in action I am found neither with certainty to the idea of where social isolation exists, but more certain that acquired experience had crafted this.  To this degree, at times, there almost seems an invocation by words of choice here, and in this sense emotion that might be encountered, although at times, this may likewise not be true, or that one may feel as lonely as one has allowed oneself in some manner.  Albeit, I would feel comfortable refraining in certainty, or at least in concession.

Meaning?

This header serves as a counter point, or the construction of a self query, whether this were something of self doubt that leads one to a given...words are sparing again in careful consideration.

Too soon and not too far removed?

This is another pitfall, among an imagined multitude of pitfalls.  Obviously returning to the point of freedom, one continuity leads into another, and careful self deliberation.  

Switching the voice

And identity?  Again not certain of this so much in a clearer way.  Obviously, if one can speak with consistent voicing...it is why one learns through some manner of devised self testing that irony falls flat in some way if a flow between logical styles is disruptive to the degree of clarity.   How does one develop a sense over time in using any one particular device by natural extension without relying upon a given social test, for instance.  That is, testing an idea to the degree that someone scratches one's head, or a critic.  Whether this is given to an abundance of writing, an over exertion, overly thinking one's writing.

Straying from convention

I've written about this in so many words before.  In another way, the idea seems provokes something of disliking.  As if too often by way of convention, the writer appeals to the sensibility in producing a product while railing against being identified as a product.  A style of mind is unfortunately given to this convention, is it not?  Or more so to artistic hegemony.  People pay to see the reproductions of an artist that seem artistically the art of an artist, or style that deviates, in this way is somehow the reflection of something that were less than authentic to self reproduction.  Social cultivation leads one to a given experience, refinement, and set social expectation.  Invariably in the modern age, this could be to the laughable charge, 'hipsters' something, or at least hopefully a cute self righteous affectation.  So much the peril, to social deviations here...granted this is tolerable for film makers...you can after all direct, The Incredible Hulk, and still produce a fine art film.

 Please refrain from publication for a time on this one

Should this be more obvious.  This is merely something like an ice breaker, or relaxation of mind when all seems to serious about the world.  

Oblivion

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