예제 #1
0
파일: Bvh.cpp 프로젝트: NCCA/NGL6Demos
ngl::Mat4 Bvh::getRotationFromZ(ngl::Vec3 _vec) const
{
    ngl::Mat4 rotM;
    float x, y, z;
    // rotate negative z axis to _vec direction
    _vec.normalize();
    ngl::Vec3 nz(0,0,-1);
    float angle = acos(_vec.dot(nz));
    ngl::Vec3 norm = _vec.cross(nz);
    if(norm.length()<= 0.0001)
    {
        x= z = 0.0;
        y = 1.0;
    }
    else
    {
        norm.normalize();
        x = norm.m_x;
        y = norm.m_y;
        z = norm.m_z;
    }

    // Axis and Angle matrix rotation see
    // http://en.wikipedia.org/wiki/Rotation_matrix for more details
    float c = cos(angle);
    float s = sin(angle);
    float C=1-c;
    float xs  = x*s;  float  ys = y*s;  float  zs = z*s;
    float xC  = x*C;  float  yC = y*C;  float  zC = z*C;
    float xyC = x*yC; float yzC = y*zC; float zxC = z*xC;

    rotM.m_m[0][0]=x*xC+c;  rotM.m_m[0][1]= xyC-zs;  rotM.m_m[0][2]= zxC+ys;
    rotM.m_m[1][0]=xyC+zs;   rotM.m_m[1][1]=y*yC+c;  rotM.m_m[1][2]= yzC-xs;
    rotM.m_m[2][0]=zxC-ys;   rotM.m_m[2][1]=yzC+xs;  rotM.m_m[2][2]=z*zC+c;
    return rotM;
}
void NGLScene::paintGL()
{

    if(testangle==89)
        vary=-1;

    if(testangle==-89)
        vary=1;

//This bit has been  MOVED TO TIMER EVENT for more 'slow-motion' control
//    testangle+=vary;
    std::cout<<testangle<<std::endl;

    ngl::Vec3 v1(-5+15*sin((testangle)*(M_PI/180))-2,-5+15*sin((testangle)*(M_PI/180)),  4*sin((testangle)*(M_PI/180))-2);
    ngl::Vec3 v2(-4,0.01,-5+15*sin((testangle)*(M_PI/180)));//transform the triangle vao to 2,2,0

      ngl::Vec3 v2NonNormalized=v2;
      ngl::Vec3 v1NonNormalized=v1;


  // clear the screen and depth buffer
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  // Rotation based on the mouse position for our global transform

  // Rotation based on the mouse position for our global
  // transform
  ngl::Mat4 rotX;
  ngl::Mat4 rotY;
  // create the rotation matrices
  rotX.rotateX(m_spinXFace);
  rotY.rotateY(m_spinYFace);
  // multiply the rotations
  m_mouseGlobalTX=rotY*rotX;
  // add the translations
  m_mouseGlobalTX.m_m[3][0] = m_modelPos.m_x;
  m_mouseGlobalTX.m_m[3][1] = m_modelPos.m_y;
  m_mouseGlobalTX.m_m[3][2] = m_modelPos.m_z;


  ngl::ShaderLib *shader=ngl::ShaderLib::instance();
  (*shader)["Phong"]->use();
  ngl::Material m(ngl::STDMAT::PEWTER);
  // load our material values to the shader into the structure material (see Vertex shader)
  m.loadToShader("material");

  ngl::Mat4 MV;
  ngl::Mat4 MVP;
  ngl::Mat3 normalMatrix;
  ngl::Mat4 M;


  //*********
  m_transform.reset();
  //draw box
  {
      m_transform.setPosition(v1NonNormalized);
      M=m_transform.getMatrix()*m_mouseGlobalTX;
      MV=  M*m_cam->getViewMatrix();
      MVP= M*m_cam->getVPMatrix();
      normalMatrix=MV;
      normalMatrix.inverse();
      shader->setShaderParamFromMat4("MV",MV);
      shader->setShaderParamFromMat4("MVP",MVP);
      shader->setShaderParamFromMat3("normalMatrix",normalMatrix);
      shader->setShaderParamFromMat4("M",M);


      //ngl::VAOPrimitives::instance()->draw("cube");
      m_vao2->bind();
      m_vao2->draw();
      m_vao2->unbind();

  }


    v1.normalize();
    v2.normalize();
    float angle = /*atan2(v1.m_y,v1.m_x) - atan2(v2.m_y,v2.m_x);//*/acos(v1.dot(v2));

    ngl::Vec3 rotationAxis = v1.cross(v2);
    rotationAxis.normalize();

//    ngl::Quaternion q ;
//    q.fromAxisAngle(rotationAxis,angle);

    ngl::Mat4 s,rotateMat,translateMat;
    s=1;

    //Use either RotationBetweenVectors or matrixFromAxisAngle
    rotateMat=RotationBetweenVectors(v2,v1).toMat4();
    //rotateMat=matrixFromAxisAngle(rotationAxis,angle);//q.toMat4();


    //calculate euler angles from axis-angle
//    double heading,attitude,bank;
//    toEuler(rotationAxis.m_x, rotationAxis.m_y, rotationAxis.m_z, angle, heading, attitude, bank);

//    m_transform.reset();
//    std::cout<<bank*(180/M_PI)<<","<<heading*(180/M_PI)<<","<<attitude*(180/M_PI)<<","<<std::endl;
//    m_transform.setRotation(bank*(180/M_PI),heading*(180/M_PI),attitude*(180/M_PI));
//    r= m_transform.getMatrix();

    m_transform.reset();
    m_transform.setPosition(v2NonNormalized);
    translateMat= m_transform.getMatrix();

    ngl::Mat4 modelmatrix=s*rotateMat*translateMat;

  m_transform.reset();
  //draw triangle
  {
      //    load our material values to the shader into the structure material (see Vertex shader)
      m.set(ngl::STDMAT::BRONZE);
      m.loadToShader("material");

      M=/*m_transform.getMatrix()*/  modelmatrix*m_mouseGlobalTX;
      MV=  M*m_cam->getViewMatrix();
      MVP= M*m_cam->getVPMatrix();
      normalMatrix=MV;
      normalMatrix.inverse();
      shader->setShaderParamFromMat4("MV",MV);
      shader->setShaderParamFromMat4("MVP",MVP);
      shader->setShaderParamFromMat3("normalMatrix",normalMatrix);
      shader->setShaderParamFromMat4("M",M);


//      ngl::VAOPrimitives::instance()->draw("cube");
      m_vao->bind();
      m_vao->draw();
      m_vao->unbind();

   }



//    //draw the tip-cube of the triangle
//  {
//    m.set(ngl::GOLD);
//    // load our material values to the shader into the structure material (see Vertex shader)
//    m.loadToShader("material");

//    translateMat=1;

//  //  rotateMat=1;
//  //  scaleMat=1;

//  //not working
//  //  ngl::Vec3 v=v1.cross(v2);
//  //  float c=v1.dot(v2);
//  //  float h=1-c/v.dot(v);
//  //  rotateMat=ngl::Mat4(c*h*v.m_x*v.m_x,                 h*v.m_x*v.m_y-v.m_z,           h*v.m_x*v.m_z+v.m_y, 1,
//  //                      h*v.m_x*v.m_y+v.m_z,             c+h*v.m_y*v.m_y,               h*v.m_y*v.m_z-v.m_x, 1,
//  //                      h*v.m_x*v.m_z-v.m_y,       h*v.m_y*v.m_z+v.m_x,                c+h*v.m_z*v.m_z,      1,
//  //                      0 ,                            0 ,                                     0,            1);
//  //  rotateMat.transpose();
//  //not working



//  //     ngl::Mat4 trs=m_transform.getMatrix();
//  //     rotateMat=matrixFromAxisAngle(rotationAxis,angle);
//  //     translateMat.translate(-v2NonNormalized.m_x,-(v2NonNormalized.m_y),-v2NonNormalized.m_z);

//    //Based on [R] = [T].inverse * [R0] * [T] //http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/
//    /*
//      translate the arbitrary point to the origin (subtract P which is translate by -Px,-Py,-Pz)
//      rotate about the origin (can use 3×3 matrix R0)
//      then translate back. (add P which is translate by +Px,+Py,+Pz)
//    */
//       translateMat.inverse();//step 1.. translate pointToRotate to origin

//       //(rotation matrix) - same as the triangle's "rotateMat" //step 2 rotate..

//       translateMat2.translate(v2NonNormalized.m_x,(v2NonNormalized.m_y),v2NonNormalized.m_z);//step3 ..translate pointToRotate back to its original position in 3d space

//       std::cout<<translateMat2.m_30<<","<<translateMat2.m_31<<","<<translateMat2.m_32<<std::endl;



//  //     std::cout<<"mat Matrix():\n"<<"  "<<rotateMat.m_00<<"  "<< rotateMat.m_01<<"  "<<rotateMat.m_02 <<"  "<<rotateMat.m_03<<"  "<<
//  //                                    rotateMat.m_10<<"  "<< rotateMat.m_11<<"  "<<rotateMat.m_12 <<"  "<<rotateMat.m_13<<"  "<< rotateMat.m_20<<"  "<< rotateMat.m_21<<"  "<<rotateMat.m_22 <<"  "<<rotateMat.m_23<<"  "<< rotateMat.m_30<<"  "<<
//  //                                    rotateMat.m_31<<"  "<<rotateMat.m_32 <<"  "<<rotateMat.m_33<<"  "<<std::endl;

//  //     std::cout<<angle<<std::endl;

//       //place one one sphere-primitive in the tip of the triangle, but we translate first and then rotate (this effectively shows the "trajectory of the triangle rotation")

//       /*
//        * In order to calculate the rotation about any arbitrary point we need to calculate its new rotation and translation.
//        * In other words rotation about a point is an 'proper' isometry transformation' which means that it has a linear
//        *  and a rotational component.
//        * [resulting transform] = [+Px,+Py,+Pz] * [rotation] * [-Px,-Py,-Pz]
//        */


//        M=  translateMat*rotateMat*translateMat2 /**scaleMat*/; //in ngl multiplication happens from left to right

//        M= M*m_mouseGlobalTX;
//        MV=  M*m_cam->getViewMatrix();
//        MVP= M*m_cam->getVPMatrix();
//        normalMatrix=MV;
//        normalMatrix.inverse();
//        shader->setShaderParamFromMat4("MV",MV);
//        shader->setShaderParamFromMat4("MVP",MVP);
//        shader->setShaderParamFromMat3("normalMatrix",normalMatrix);
//        shader->setShaderParamFromMat4("M",M);

////        ngl::VAOPrimitives::instance()->createSphere("mysphere",0.1,10);

//        ngl::VAOPrimitives::instance()->draw("cube");

//  }















//  //*********NOW********* STEP 2
//  //Calculate rotation vector from 2nd to 1st triangle
//  //then

//  m.set(ngl::BRONZE);
//  // load our material values to the shader into the structure material (see Vertex shader)
//  m.loadToShader("material");

//  //... rotate and draw the 2nd triangle as well
//  m_transform.reset();
//  {

////------------------------------------------------------------------------------------------------------------------------------------
////------------------------------------------------------------------------------------------------------------------------------------
///**************
////not working
////     eulerAngles.m_x = atan2( rotationAxis.m_y, rotationAxis.m_z );
////     if (rotationAxis.m_z >= 0) {
////        eulerAngles.m_y = -atan2( rotationAxis.m_x * cos(eulerAngles.m_x), rotationAxis.m_z );
////     }else{
////        eulerAngles.m_y = atan2( rotationAxis.m_x * cos(eulerAngles.m_x), -rotationAxis.m_z );
////     }

////     eulerAngles.m_z = atan2( cos(eulerAngles.m_x), sin(eulerAngles.m_x) * sin(eulerAngles.m_y) );


//     //
////     eulerAngles.m_x= 0;
////     eulerAngles.m_y = atan2((v1-v2).m_x, (v1-v2).m_z);
////     float padj = sqrt(pow((v1-v2).m_x, 2) + pow((v1-v2).m_z, 2));
////     eulerAngles.m_y = atan2(padj, (v1-v2).m_y) ;

//  **************/
//     //convert axis anle to euler angles
////     toEuler(rotationAxis.m_x, rotationAxis.m_y, rotationAxis.m_z, angle);
////     m_transform.setRotation(eulerAngles.m_x*(180/M_PI),eulerAngles.m_y*(180/M_PI),eulerAngles.m_z*(180/M_PI));
//       ngl::Mat4 trs=m_transform.getMatrix();
////------------------------------------------------------------------------------------------------------------------------------------
////------------------------------------------------------------------------------------------------------------------------------------



//    //The following work with ngl::Transformation too, as well as with individual matrices
//    //       m_transform.reset();
//    //       if(testangle<360)
//    //           testangle++;
//    //       else
//    //       {
//    //           testangle=0;
//    //       }

//    //       m_transform.setRotation(testangle,0,0);

//    //Rotate based where v1 is (make v2NonNormalized(triangle) to point towards v1-cube)
//     rotateMat=matrixFromAxisAngle(rotationAxis,angle);//m_transform.getMatrix();
//     translateMat.translate(v2NonNormalized.m_x,v2NonNormalized.m_y,v2NonNormalized.m_z);


////     std::cout<<"mat Matrix():\n"<<"  "<<rotateMat.m_00<<"  "<< rotateMat.m_01<<"  "<<rotateMat.m_02 <<"  "<<rotateMat.m_03<<"  "<<
////                                    rotateMat.m_10<<"  "<< rotateMat.m_11<<"  "<<rotateMat.m_12 <<"  "<<rotateMat.m_13<<"  "<< rotateMat.m_20<<"  "<< rotateMat.m_21<<"  "<<rotateMat.m_22 <<"  "<<rotateMat.m_23<<"  "<< rotateMat.m_30<<"  "<<
////                                    rotateMat.m_31<<"  "<<rotateMat.m_32 <<"  "<<rotateMat.m_33<<"  "<<std::endl;
////     std::cout<<angle<<std::endl;




////not quite working
//        float norm_u_norm_v = sqrt(v2NonNormalized.lengthSquared() * v1NonNormalized.lengthSquared());
//        ngl::Vec3 w = v2.cross(v1);
//        ngl::Quaternion q = ngl::Quaternion(norm_u_norm_v + v2NonNormalized.dot(v1NonNormalized), w.m_x, w.m_y, w.m_z);
//        q.normalise();
//        rotateMat=q.toMat4();

////not quite working either
//     rotateMat=ngl::lookAt(v2NonNormalized,v1NonNormalized,ngl::Vec3(0,1,0));



//      M=rotateMat*translateMat;//left to right multiplication in ngl (first rotate then translate)

//      M=/*m_transform.getMatrix()*/ M/* trs*/*m_mouseGlobalTX;
//      MV=  M*m_cam->getViewMatrix();
//      MVP= M*m_cam->getVPMatrix();
//      normalMatrix=MV;
//      normalMatrix.inverse();
//      shader->setShaderParamFromMat4("MV",MV);
//      shader->setShaderParamFromMat4("MVP",MVP);
//      shader->setShaderParamFromMat3("normalMatrix",normalMatrix);
//      shader->setShaderParamFromMat4("M",M);


//      m_vao->bind();
//      m_vao->draw();//draw triangle now
//      m_vao->unbind();
//  }


//  //*********NOW********* STEP 3

//  //draw the tip-cube of the triangle
//{
//  m.set(ngl::GOLD);
//  // load our material values to the shader into the structure material (see Vertex shader)
//  m.loadToShader("material");

//  translateMat=1;

////  rotateMat=1;
////  scaleMat=1;

////not working
////  ngl::Vec3 v=v1.cross(v2);
////  float c=v1.dot(v2);
////  float h=1-c/v.dot(v);
////  rotateMat=ngl::Mat4(c*h*v.m_x*v.m_x,                 h*v.m_x*v.m_y-v.m_z,           h*v.m_x*v.m_z+v.m_y, 1,
////                      h*v.m_x*v.m_y+v.m_z,             c+h*v.m_y*v.m_y,               h*v.m_y*v.m_z-v.m_x, 1,
////                      h*v.m_x*v.m_z-v.m_y,       h*v.m_y*v.m_z+v.m_x,                c+h*v.m_z*v.m_z,      1,
////                      0 ,                            0 ,                                     0,            1);
////  rotateMat.transpose();
////not working



////     ngl::Mat4 trs=m_transform.getMatrix();
////     rotateMat=matrixFromAxisAngle(rotationAxis,angle);
////     translateMat.translate(-v2NonNormalized.m_x,-(v2NonNormalized.m_y),-v2NonNormalized.m_z);

//  //Based on [R] = [T].inverse * [R0] * [T] //http://www.euclideanspace.com/maths/geometry/affine/aroundPoint/
//  /*
//    translate the arbitrary point to the origin (subtract P which is translate by -Px,-Py,-Pz)
//    rotate about the origin (can use 3×3 matrix R0)
//    then translate back. (add P which is translate by +Px,+Py,+Pz)
//  */
//     translateMat.inverse();//step 1.. translate pointToRotate to origin

//     //(rotation matrix) - same as the triangle's "rotateMat" //step 2 rotate..

//     translateMat2.translate(v2NonNormalized.m_x,(v2NonNormalized.m_y),v2NonNormalized.m_z);//step3 ..translate pointToRotate back to its original position in 3d space

//     std::cout<<translateMat2.m_30<<","<<translateMat2.m_31<<","<<translateMat2.m_32<<std::endl;



////     std::cout<<"mat Matrix():\n"<<"  "<<rotateMat.m_00<<"  "<< rotateMat.m_01<<"  "<<rotateMat.m_02 <<"  "<<rotateMat.m_03<<"  "<<
////                                    rotateMat.m_10<<"  "<< rotateMat.m_11<<"  "<<rotateMat.m_12 <<"  "<<rotateMat.m_13<<"  "<< rotateMat.m_20<<"  "<< rotateMat.m_21<<"  "<<rotateMat.m_22 <<"  "<<rotateMat.m_23<<"  "<< rotateMat.m_30<<"  "<<
////                                    rotateMat.m_31<<"  "<<rotateMat.m_32 <<"  "<<rotateMat.m_33<<"  "<<std::endl;

////     std::cout<<angle<<std::endl;

//     //place one one sphere-primitive in the tip of the triangle, but we translate first and then rotate (this effectively shows the "trajectory of the triangle rotation")

//     /*
//      * In order to calculate the rotation about any arbitrary point we need to calculate its new rotation and translation.
//      * In other words rotation about a point is an 'proper' isometry transformation' which means that it has a linear
//      *  and a rotational component.
//      * [resulting transform] = [+Px,+Py,+Pz] * [rotation] * [-Px,-Py,-Pz]
//      */


//      M=  translateMat*rotateMat*translateMat2 /**scaleMat*/; //in ngl multiplication happens from left to right

//      M= M*m_mouseGlobalTX;
//      MV=  M*m_cam->getViewMatrix();
//      MVP= M*m_cam->getVPMatrix();
//      normalMatrix=MV;
//      normalMatrix.inverse();
//      shader->setShaderParamFromMat4("MV",MV);
//      shader->setShaderParamFromMat4("MVP",MVP);
//      shader->setShaderParamFromMat3("normalMatrix",normalMatrix);
//      shader->setShaderParamFromMat4("M",M);

//      ngl::VAOPrimitives::instance()->createSphere("mysphere",0.1,10);

//      ngl::VAOPrimitives::instance()->draw("cube");

//}



}
//return shortest arc quaternion that rotates start to dest
 ngl::Quaternion NGLScene::RotationBetweenVectors(ngl::Vec3 start, ngl::Vec3  dest){

     ngl::Quaternion q;

     (start).normalize();

     (dest).normalize();



     float cosTheta = start.dot(dest);

     ngl::Vec3  rotationAxis;


     /**
      * https://bitbucket.org/sinbad/ogre/src/9db75e3ba05c/OgreMain/include/OgreVector3.h?fileviewer=file-view-default#cl-651
      *
      * Gets the shortest arc quaternion to rotate this vector to the destination
                vector.
            @remarks
                If you call this with a dest vector that is close to the inverse
                of this vector, we will rotate 180 degrees around the 'fallbackAxis'
                (if specified, or a generated axis if not) since in this case
                ANY axis of rotation is valid.
 */
     if (cosTheta >= 1.0f)//same vectors
     {
         return ngl::Quaternion();//identity quaternion
     }

     if (cosTheta < (1e-6f - 1.0f))
     {
         // Generate an axis
         rotationAxis = ngl::Vec3 (0.0f, 0.0f, 1.0f).cross( start);

         if (rotationAxis.length()==0) // pick another if colinear
             rotationAxis = ngl::Vec3 (0.0f, 1.0f, 0.0f).cross( start);

         rotationAxis.normalize();
         q.fromAxisAngle(rotationAxis,180.0f);
     }




 //    if (cosTheta < -1 + 0.001f)
 //    {

 //        // special case when vectors in opposite directions:

 //        // there is no "ideal" rotation axis

 //        // So guess one; any will do as long as it's perpendicular to start

 //        rotationAxis = ngl::Vec3 (0.0f, 0.0f, 1.0f).cross( start);

 //        float t=rotationAxis.lengthSquared();
 //        if (t< 0.01 ) // bad luck, they were parallel, try again!

 //            rotationAxis = ngl::Vec3 (1.0f, 0.0f, 0.0f).cross( start);


 //        (rotationAxis).normalize();

 //        q.fromAxisAngle(rotationAxis,180.0f);

 //        return q;
 //    }



     rotationAxis = start.cross(dest);



     float s = sqrt( (1+cosTheta)*2 );

     float invs = 1 / s;



     return ngl::Quaternion(

         s * 0.5f,

         rotationAxis.m_x * invs,

         rotationAxis.m_y * invs,

         rotationAxis.m_z * invs

     );


  }