/*! Load the xml configuration file. From the configuration file initialize the parameters corresponding to the objects: KLT, camera. \warning To clean up memory allocated by the xml library, the user has to call vpXmlParser::cleanup() before the exit(). \throw vpException::ioError if the file has not been properly parsed (file not found or wrong format for the data). \param configFile : full name of the xml file. The XML configuration file has the following form: \code <?xml version="1.0"?> <conf> <camera> <width>640</width> <height>480</height> <u0>320</u0> <v0>240</v0> <px>686.24</px> <py>686.24</py> </camera> <face> <angle_appear>65</angle_appear> <angle_disappear>85</angle_disappear> <near_clipping>0.01</near_clipping> <far_clipping>0.90</far_clipping> <fov_clipping>1</fov_clipping> </face> <klt> <mask_border>10</mask_border> <max_features>10000</max_features> <window_size>5</window_size> <quality>0.02</quality> <min_distance>10</min_distance> <harris>0.02</harris> <size_block>3</size_block> <pyramid_lvl>3</pyramid_lvl> </klt> </conf> \endcode \sa loadConfigFile(const std::string&), vpXmlParser::cleanup() */ void vpMbKltTracker::loadConfigFile(const char* configFile) { #ifdef VISP_HAVE_XML2 vpMbtKltXmlParser xmlp; xmlp.setMaxFeatures(10000); xmlp.setWindowSize(5); xmlp.setQuality(0.01); xmlp.setMinDistance(5); xmlp.setHarrisParam(0.01); xmlp.setBlockSize(3); xmlp.setPyramidLevels(3); xmlp.setMaskBorder(maskBorder); xmlp.setAngleAppear(vpMath::deg(angleAppears)); xmlp.setAngleDisappear(vpMath::deg(angleDisappears)); try{ std::cout << " *********** Parsing XML for MBT KLT Tracker ************ " << std::endl; xmlp.parse(configFile); } catch(...){ vpERROR_TRACE("Can't open XML file \"%s\"\n ", configFile); throw vpException(vpException::ioError, "problem to parse configuration file."); } vpCameraParameters camera; xmlp.getCameraParameters(camera); setCameraParameters(camera); tracker.setMaxFeatures((int)xmlp.getMaxFeatures()); tracker.setWindowSize((int)xmlp.getWindowSize()); tracker.setQuality(xmlp.getQuality()); tracker.setMinDistance(xmlp.getMinDistance()); tracker.setHarrisFreeParameter(xmlp.getHarrisParam()); tracker.setBlockSize((int)xmlp.getBlockSize()); tracker.setPyramidLevels((int)xmlp.getPyramidLevels()); maskBorder = xmlp.getMaskBorder(); angleAppears = vpMath::rad(xmlp.getAngleAppear()); angleDisappears = vpMath::rad(xmlp.getAngleDisappear()); //if(useScanLine) faces.getMbScanLineRenderer().setMaskBorder(maskBorder); if(xmlp.hasNearClippingDistance()) setNearClippingDistance(xmlp.getNearClippingDistance()); if(xmlp.hasFarClippingDistance()) setFarClippingDistance(xmlp.getFarClippingDistance()); if(xmlp.getFovClipping()) setClipping(clippingFlag = clippingFlag | vpPolygon3D::FOV_CLIPPING); useLodGeneral = xmlp.getLodState(); minLineLengthThresholdGeneral = xmlp.getMinLineLengthThreshold(); minPolygonAreaThresholdGeneral = xmlp.getMinPolygonAreaThreshold(); applyLodSettingInConfig = false; if(this->getNbPolygon() > 0) { applyLodSettingInConfig = true; setLod(useLodGeneral); setMinLineLengthThresh(minLineLengthThresholdGeneral); setMinPolygonAreaThresh(minPolygonAreaThresholdGeneral); } #else vpTRACE("You need the libXML2 to read the config file %s", configFile); #endif }
CC3Vector CC3Camera::calculateLocationToShowAllOf( CC3Node* aNode, const CC3Vector& targLoc, const CC3Vector& aDirection, GLfloat padding, bool checkScene ) { ensureSceneUpdated( checkScene ); // Complementary unit vectors pointing towards camera from node, and vice versa CC3Vector camDir = aDirection.normalize(); CC3Vector viewDir = camDir.negate(); // The camera's new forward direction will be viewDir. Use a matrix to detrmine // the camera's new up and right directions assuming the same scene up direction. CC3Matrix3x3 rotMtx; CC3Matrix3x3PopulateToPointTowards(&rotMtx, viewDir, getReferenceUpDirection()); CC3Vector upDir = CC3Matrix3x3ExtractUpDirection(&rotMtx); CC3Vector rtDir = CC3Matrix3x3ExtractRightDirection(&rotMtx); // Determine the eight vertices, of the node's bounding box, in the global coordinate system CC3Box gbb = aNode->getGlobalBoundingBox(); CC3Vector targetLoc = targLoc; // If a target location has not been specified, use the center of the node's global bounding box if ( targetLoc.isNull() ) targetLoc = gbb.getCenter(); CC3Vector bbMin = gbb.minimum; CC3Vector bbMax = gbb.maximum; CC3Vector bbVertices[8]; bbVertices[0] = cc3v(bbMin.x, bbMin.y, bbMin.z); bbVertices[1] = cc3v(bbMin.x, bbMin.y, bbMax.z); bbVertices[2] = cc3v(bbMin.x, bbMax.y, bbMin.z); bbVertices[3] = cc3v(bbMin.x, bbMax.y, bbMax.z); bbVertices[4] = cc3v(bbMax.x, bbMin.y, bbMin.z); bbVertices[5] = cc3v(bbMax.x, bbMin.y, bbMax.z); bbVertices[6] = cc3v(bbMax.x, bbMax.y, bbMin.z); bbVertices[7] = cc3v(bbMax.x, bbMax.y, bbMax.z); // Express the camera's FOV in terms of ratios of the near clip bounds to // the near clip distance, so we can determine distances using similar triangles. CCSize fovRatios = getFovRatios(); // Iterate through all eight vertices of the node's bounding box, and calculate // the largest distance required to place the camera away from the center of the // node in order to fit all eight vertices within the camera's frustum. // Simultaneously, calculate the extra distance from the center of the node to // the vertex that will be farthest from the camera, so we can ensure that all // vertices will fall within the frustum's far end. GLfloat maxCtrDist = 0; GLfloat maxVtxDeltaDist = 0; GLfloat minVtxDeltaDist = 0; for (int i = 0; i < 8; i++) { // Get a vector from the target location to the vertex CC3Vector relVtx = bbVertices[i] - targetLoc; // Project that vector onto each of the camera's new up and right directions, // and use similar triangles to determine the distance at which to place the // camera so that the vertex will fit in both the up and right directions. GLfloat vtxDistUp = fabs(relVtx.dot( upDir ) / fovRatios.height); GLfloat vtxDistRt = fabs(relVtx.dot( rtDir ) / fovRatios.width); GLfloat vtxDist = MAX(vtxDistUp, vtxDistRt); // Calculate how far along the view direction the vertex is from the center GLfloat vtxDeltaDist = relVtx.dot( viewDir ); GLfloat ctrDist = vtxDist - vtxDeltaDist; // Accumulate the maximum distance from the node's center to the camera // required to fit all eight points, and the distance from the node's // center to the vertex that will be farthest away from the camera. maxCtrDist = MAX(maxCtrDist, ctrDist); maxVtxDeltaDist = MAX(maxVtxDeltaDist, vtxDeltaDist); minVtxDeltaDist = MIN(minVtxDeltaDist, vtxDeltaDist); } // Add some padding so we will have a bit of space around the node when it fills the view. maxCtrDist *= (1 + padding); // Determine if we need to move the far end of the camera frustum farther away GLfloat farClip = viewDir.scaleUniform(maxCtrDist + maxVtxDeltaDist).length(); farClip *= (GLfloat)(1 + kCC3FrustumFitPadding); // Include a little bit of padding if (farClip > getFarClippingDistance()) setFarClippingDistance( farClip ); // Determine if we need to move the near end of the camera frustum closer GLfloat nearClip = viewDir.scaleUniform(maxCtrDist + minVtxDeltaDist).length(); nearClip *= (GLfloat)(1 - kCC3FrustumFitPadding); // Include a little bit of padding if (nearClip < getNearClippingDistance()) setNearClippingDistance( nearClip ); //LogTrace(@"%@ moving to %@ to show %@ at %@ within %@ with new farClip: %.3f", self, // NSStringFromCC3Vector(CC3VectorAdd(targLoc, CC3VectorScaleUniform(camDir, maxCtrDist))), // aNode, NSStringFromCC3Vector(targLoc), _frustum, self.farClippingDistance); // Return the new location of the camera, return targetLoc.add( camDir.scaleUniform( maxCtrDist ) ); }