void OrbitCameraManipulator::computeRayPointer( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ) { osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); if (!view) return; m_model_screen.makeIdentity(); // do not apply viewport here ( m_cam->getViewport()->computeWindowMatrix() ). Use normalized screen coords instead (ea.getXnormalized()) osg::Matrixd pm( view->getCamera()->getProjectionMatrix() ); osg::Matrixd vm( getInverseMatrix() ); if( pm.valid() ) m_model_screen.preMult( pm ); if( vm.valid() ) m_model_screen.preMult( vm ); m_screen_model.invert( m_model_screen ); m_ray_pointer_start.set( m_screen_model.preMult( osg::Vec3d( ea.getXnormalized(), ea.getYnormalized(), 0.0) ) ); osg::Vec3d pointer_end = m_screen_model.preMult( osg::Vec3d( ea.getXnormalized(), ea.getYnormalized(), 0.1) ); osg::Vec3d ray_direction = pointer_end - m_ray_pointer_start; ray_direction.normalize(); m_ray_pointer_direction.set( ray_direction ); double fovy, apect_ratio, zNear, zFar; bool perspective = pm.getPerspective( fovy, apect_ratio, zNear, zFar ); if( perspective ) { m_fovy = fovy; } }
void MainAxisPCA::computeMainAxis(const std::vector<ml::vec3>& pointCloud) { ML_TRACE_IN("void MainAxisPCA::computeMainAxis()"); float** covaMatrix = matrix(1,3,1,3); float** jacobiMat = matrix(1,3,1,3); float** invMatrix = matrix(1,3,1,3); float* eigenValues = vL_vector(1,3); const int size = static_cast<int>( pointCloud.size() ); // copy positions to vertices float* vertices = NULL; ML_CHECK_NEW(vertices, float[size * 3]); unsigned int i=0; unsigned int entry = 0; for (i = 0; i < size; i++){ const ml::vec3& currPos = pointCloud[i]; vertices[entry++] = static_cast<float>(currPos[0]); vertices[entry++] = static_cast<float>(currPos[1]); vertices[entry++] = static_cast<float>(currPos[2]); } // Calculate center of mass ML_DELETE_ARR(_baryCenter); _baryCenter = calcBaryCenter(vertices, size); // Compute covariant matrix, so the Jacobian matrix can be computed getCovarianceMatrix(vertices, static_cast<long int>(size), covaMatrix, _baryCenter); // Compute the Jacobian matrix int nrot=0; // dummy variable jacobi(covaMatrix, 3, eigenValues, jacobiMat, &nrot); // Calculate main axes unsigned int counter=0; for (counter = 0; counter < 3; counter++) { _xAxis[counter] = jacobiMat[counter + 1][1]; _yAxis[counter] = jacobiMat[counter + 1][2]; _zAxis[counter] = jacobiMat[counter + 1][3]; } // Multiply each point by the eigenvectors of the Jacobian matrix const float* points = vertices; float* newVertices = NULL; ML_CHECK_NEW(newVertices, float[size * 3]); unsigned int counter2 = 0; for (counter = 0; counter < size; counter++) { newVertices[counter2++] = dotProduct(points, _xAxis); //tempPoint.dot(_xAxis); newVertices[counter2++] = dotProduct(points, _yAxis); //tempPoint.dot(_yAxis); newVertices[counter2++] = dotProduct(points, _zAxis); //tempPoint.dot(_zAxis); points += 3; } // Get extends of the bounding box float minX=0, maxX=0, minY=0, maxY=0, minZ=0, maxZ=0; getBoundingBox(newVertices, static_cast<long int>(size), minX, maxX, minY, maxY, minZ, maxZ); // Extends of the object aligned bounding box _xDiameter = maxX - minX; _yDiameter = maxY - minY; _zDiameter = maxZ - minZ; // Half the extend... float half_x = _xDiameter / 2.0f; float half_y = _yDiameter / 2.0f; float half_z = _zDiameter / 2.0f; // Rotate all points back by multiplying them with the inverse Jacobian matrix. getInverseMatrix(jacobiMat, invMatrix); float* tmp = stretchVector(_xAxis, half_x); for (counter = 0; counter < 3; counter++) { _midPoint[counter] = minX * invMatrix[1][counter + 1] + (minY + half_y) * invMatrix[2][counter + 1] + (minZ + half_z) * invMatrix[3][counter + 1] + tmp[counter]; } ML_DELETE_ARR(tmp); ML_DELETE_ARR(newVertices); ML_DELETE_ARR(vertices); free_matrix(covaMatrix, 1, 3, 1, 3); free_matrix(jacobiMat, 1, 3, 1, 3); free_matrix(invMatrix, 1, 3, 1, 3); free(eigenValues); }
Transform *Transform::inverse() { return new Transform(getInverseMatrix()); }
love::Vector2 Transform::inverseTransformPoint(love::Vector2 p) { love::Vector2 result; getInverseMatrix().transformXY(&result, &p, 1); return result; }
bool FPSManipulator::calcMovement() { // return if less then two events have been added. if (_ga_t0.get()==NULL || _ga_t1.get()==NULL) return false; float dx = _ga_t0->getXnormalized()-_ga_t1->getXnormalized(); float dy = _ga_t0->getYnormalized()-_ga_t1->getYnormalized(); // float distance = sqrtf(dx*dx + dy*dy); // return if there is no movement. /* if (distance==0.0f) { return false; }*/ // unsigned int buttonMask = _ga_t1->getButtonMask(); // if (buttonMask==osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)//pk for test, to be removed after { // rotate camera. float px0 = _ga_t0->getXnormalized(); float py0 = _ga_t0->getYnormalized(); float px1 = _ga_t1->getXnormalized(); float py1 = _ga_t1->getYnormalized(); //test the border to reset the position if(px0>0.9 || px0<-0.9 || py0>0.9 || py0<-0.9) { _gw->requestWarpPointer((_ga_t0->getXmax() - _ga_t0->getXmin())/2,(_ga_t0->getYmax() - _ga_t0->getYmin())/2); flushMouseEventStack(); //rest to avoid big move } double speed = _mouseScale; //default 50.0 //horizontal rotation osg::Quat qh(osg::DegreesToRadians((px1-px0)*speed), osg::Z_AXIS); //vertical rotation //rotation axis //here axis is more complex osg::Vec3d geteye, getcenter, getup; getInverseMatrix().getLookAt(geteye, getcenter, getup); osg::Vec3d front = getcenter - geteye; front.normalize(); osg::Vec3d axis = front ^ osg::Z_AXIS; axis.normalize(); //test and stop the vertical rotation double scalar = front * osg::Z_AXIS; osg::Quat qv; qv = osg::Quat(osg::DegreesToRadians((py0-py1)*speed+computeAnimation()), axis); if((scalar > 0.9 && py0 > py1 ) || (scalar < -0.9 && py0 < py1 )) //going up or down near vertical axis { qv = osg::Quat(-osg::DegreesToRadians((py0-py1)*speed), axis); //inverse rotation } //then apply the rotations _rotation = _rotation*qv*qh; return true; } /* else if (buttonMask==GUIEventAdapter::MIDDLE_MOUSE_BUTTON || buttonMask==(GUIEventAdapter::LEFT_MOUSE_BUTTON|GUIEventAdapter::RIGHT_MOUSE_BUTTON)) { // pan model. float scale = -0.3f*_distance; osg::Matrix rotation_matrix; rotation_matrix.makeRotate(_rotation); osg::Vec3 dv(dx*scale,dy*scale,0.0f); _center += dv*rotation_matrix; return true; } else if (buttonMask==GUIEventAdapter::RIGHT_MOUSE_BUTTON) { // zoom model. float fd = _distance; float scale = 1.0f+dy; if (fd*scale>_modelScale*_minimumZoomScale) { _distance *= scale; } else { // notify(DEBUG_INFO) << "Pushing forward"<<std::endl; // push the camera forward. float scale = -fd; osg::Matrix rotation_matrix(_rotation); osg::Vec3 dv = (osg::Vec3(0.0f,0.0f,-1.0f)*rotation_matrix)*(dy*scale); _center += dv; } return true; }*/ return false; }
osg::Matrixd TopView::getMatrix() const { return osg::Matrixd::inverse(getInverseMatrix()); }
void MxCore::lookAtAndFit( const osg::BoundingBox& bb ) { // We'll get the view matrix to project the bounding box, so pre-configure it // to point at the box center. Eye position doesn't matter at this point (we // compute the eye position at the end of the function). osg::Vec3d newDir = bb.center() - _position; newDir.normalize(); setDir( newDir ); // Ttransform the bounding box vertices into eye space, // then determine their x and y extents. We'll compare the eye // space bb aspect ratio against the projection _aspect to // determine the critical axis to fit. osg::ref_ptr< osg::Vec3Array > corners = new osg::Vec3Array; corners->resize( 8 ); ( *corners )[ 0 ].set( bb._min ); ( *corners )[ 1 ].set( bb._max.x(), bb._min.y(), bb._min.z() ); ( *corners )[ 2 ].set( bb._max.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 3 ].set( bb._min.x(), bb._min.y(), bb._max.z() ); ( *corners )[ 4 ].set( bb._max ); ( *corners )[ 5 ].set( bb._min.x(), bb._max.y(), bb._max.z() ); ( *corners )[ 6 ].set( bb._min.x(), bb._max.y(), bb._min.z() ); ( *corners )[ 7 ].set( bb._max.x(), bb._max.y(), bb._min.z() ); osgwTools::transform( getInverseMatrix(), corners.get() ); // The 'corners' array of bb verts are now in eye space. // Determine max and min values for eye space x and y osg::Vec2 minEC( FLT_MAX, FLT_MAX ), maxEC( FLT_MIN, FLT_MIN ); unsigned int idx; for( idx=0; idx<8; idx++ ) { const osg::Vec3& v( ( *corners )[ idx ] ); minEC[ 0 ] = osg::minimum< float >( v.x(), minEC[ 0 ] ); minEC[ 1 ] = osg::minimum< float >( v.y(), minEC[ 1 ] ); maxEC[ 0 ] = osg::maximum< float >( v.x(), maxEC[ 0 ] ); maxEC[ 1 ] = osg::maximum< float >( v.y(), maxEC[ 1 ] ); } // aspect is width (x) over height (y). const double ecWidth( maxEC[ 0 ] - minEC[ 0 ] ); const double ecHeight( maxEC[ 1 ] - minEC[ 1 ] ); const double ecAspect = ecWidth / ecHeight; // We'll store half the extent of interest into a dummy bounding sphere's radius. // We'll store the analogous fov in bestFov. osg::BoundingSphere bs; double bestFov; if( ecAspect > _aspect ) { // Fit eye space x to the view bs.radius() = ecWidth * .5; bestFov = _aspect * _fovy; } else { // Fit eye space y to the view bs.radius() = ecHeight * .5; bestFov = _fovy; } // The wrap-up code sets the eye position at the best distance from // the bb center. Extra distance is added in to account for the fact // that the input bound probably has a larger radius than the eye coord // bound that we're passing to computeInitialDistanceFromFOVY(). const double extraDistance = bb.radius() - bs.radius(); const double distance = extraDistance + osgwMx::computeInitialDistanceFromFOVY( bs, bestFov ); setPosition( bs.center() - ( newDir * distance ) ); }
//Comparison speed: 10.96 //Bounding Boxes: 5.89 //Ordering: 4.99 double RayGroup::intersect(Ray3D ray,RayIntersectionInfo& iInfo,double mx){ //printf("This runs\n"); bool ignoreMX = false; if (mx == -1) ignoreMX = true; Ray3D rayCopy = Ray3D(); rayCopy.position = ray.position; rayCopy.direction = ray.direction; double min_t = -1; RayShape* min_shape = NULL; RayIntersectionInfo tempInfo = RayIntersectionInfo(); double boxOut = bBox.intersect(ray); if (boxOut < mx || ignoreMX){ if(boxOut > -1){ Matrix4D matrix = getMatrix(); ray.position = getInverseMatrix().multPosition(ray.position); ray.direction = getInverseMatrix().multDirection(ray.direction); double scaler = ray.direction.length(); ray.direction = ray.direction.unit(); int count = 0; for (int i = 0; i < sNum; i++) { RayShape* temp = shapes[i]; double dist = temp->bBox.intersect(ray); if(dist < mx || ignoreMX) { if (dist > -1) { //Means we have a hit of the inner volume hits[count].shape = temp; hits[count].t = dist; count++; } } } qsort(hits,count,sizeof(RayShapeHit),RayShapeHit::Compare); //if (bBox.intersect(ray) > -1){ for (int i = 0; i < count; i++) { //printf("something got hit!\n"); //printf("i = %i\n",i); RayShape* temp = hits[i].shape; double t = -1; t = temp->intersect(ray, tempInfo, mx); if (t > 0) { t = t / scaler; if (min_t == -1 || t < min_t) { min_t = t; min_shape = temp; iInfo.iCoordinate = tempInfo.iCoordinate; iInfo.normal = tempInfo.normal; iInfo.material = tempInfo.material; break; } } //Checks if its a Static Ray Group with its own transform information /*StaticRayGroup* temp2 = dynamic_cast<StaticRayGroup*>(temp); if(temp2 != 0) { t = temp->intersect(rayCopy, tempInfo, mx); if (t > 0) { if (min_t == -1 || t < min_t) { iInfo.iCoordinate = tempInfo.iCoordinate; iInfo.normal = tempInfo.normal; iInfo.material = tempInfo.material; min_t = t; min_shape = temp; } } } else { ray.position = getInverseMatrix().multPosition(rayCopy.position); ray.direction = getInverseMatrix().multDirection(rayCopy.direction).unit(); t = temp->intersect(ray, tempInfo, mx); if (t > 0) { if (min_t == -1 || t < min_t) { iInfo.iCoordinate = matrix.multPosition(tempInfo.iCoordinate); iInfo.normal = getNormalMatrix().multNormal(tempInfo.normal); iInfo.material = tempInfo.material; min_t = t; min_shape = temp; } } }*/ } iInfo.iCoordinate = matrix.multPosition(iInfo.iCoordinate); iInfo.normal = getNormalMatrix().multDirection(iInfo.normal).unit(); //iInfo.material = iInfo.material; } } return min_t; }
bool MyFirstPersonCamManipulator::handleKeyDown(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) { switch (ea.getKey()) { case osgGA::GUIEventAdapter::KEY_KP_Space: home(0.0); break; case 'r': //_rotation.makeRotate(3.1415926535/2,1.0,0.0,0.0); { osg::Vec3 eye; osg::Vec3 dir; osg::Vec3 up; getInverseMatrix().getLookAt(eye,dir,up); osg::Vec3 Look=dir-eye; float AngleBetweenAxisAndZ; float dot=osg::Vec3(0.0,0.0,1.0)*up; AngleBetweenAxisAndZ=acos(dot); osg::Quat restore; if(Look.z()>0.0) restore.makeRotate(AngleBetweenAxisAndZ,-1.0,0.0,0.0); else if(Look.z()<0.0) restore.makeRotate(AngleBetweenAxisAndZ,1.0,0.0,0.0); else {} _rotation=restore*_rotation; break; } case 'w': if(!move&&(currentKey=='w')) { _eye+=_rotation*osg::Vec3d(0.0,0.0,2.0); move=true; break; } else if(!move&&(currentKey=='s')) { _eye+=_rotation*osg::Vec3d(0.0,0.0,-2.0); move=true; //break; } currentKey='w'; _eye+=_rotation*osg::Vec3d(0.0,0.0,-1.0); break; case 's': if(!move&&(currentKey=='s')) { _eye+=_rotation*osg::Vec3d(0.0,0.0,-2.0); move=true; break; } else if(!move&&(currentKey=='w')) { _eye+=_rotation*osg::Vec3d(0.0,0.0,2.0); move=true; //break; } currentKey='s'; _eye+=_rotation*osg::Vec3d(0.0,0.0,1.0); break; default: break; } }