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 ); }