コード例 #1
0
void  OgreWidget::mouseMoveEvent(QMouseEvent * e)
{
  if (m_oldPos != InvalidMousePoint)
    {
      Ogre::Real deltaX = e->pos().x() - m_oldPos.x();
      Ogre::Real deltaY = e->pos().y() - m_oldPos.y();

      if (m_mouseButtonsPressed.testFlag(Qt::MiddleButton))
        {
          if(e->modifiers().testFlag(Qt::ControlModifier))
            m_camera->zoom(-deltaY);
          else if (e->modifiers().testFlag(Qt::ShiftModifier))
            m_camera->rotate(deltaX, -deltaY);
          else
            m_camera->shift(-deltaX, -deltaY);
        }
      else if (m_mouseButtonsPressed.testFlag(Qt::LeftButton) && !m_selectionManager.isEmpty())
        {
          if (m_constraintedX && e->modifiers().testFlag(Qt::ShiftModifier))
            m_selectionManager.pitch(Ogre::Degree(deltaX));
          else if (m_constraintedY && e->modifiers().testFlag(Qt::ShiftModifier))
            m_selectionManager.yaw(Ogre::Degree(deltaX));
          else if (m_constraintedZ && e->modifiers().testFlag(Qt::ShiftModifier))
            m_selectionManager.roll(Ogre::Degree(deltaX));
          else
            {
              Ogre::Plane plane;

              if (m_constraintedX)
                plane.redefine(Ogre::Vector3(1, 0, 0), m_selectionManager.getPosition());
              else if (m_constraintedY)
                plane.redefine(Ogre::Vector3(0, 1, 0), m_selectionManager.getPosition());
              else if (m_constraintedZ)
                plane.redefine(Ogre::Vector3(0, 0, 1), m_selectionManager.getPosition());

              Ogre::Ray                   oldRay = m_camera->getCamera()->getCameraToViewportRay(e->pos().x() / (float)width(), e->pos().y() / (float)height());
              Ogre::Ray                   ray = m_camera->getCamera()->getCameraToViewportRay(m_oldPos.x() / (float)width(), m_oldPos.y() / (float)height());
              std::pair<bool, Ogre::Real> oldResult = oldRay.intersects(plane);
              std::pair<bool, Ogre::Real> result = ray.intersects(plane);

              if (result.first && oldResult.first)
                {
                  Ogre::Vector3 point;

                  point = oldRay.getPoint(oldResult.second) - ray.getPoint(result.second);
                  m_selectionManager.translate(point.x, point.y, point.z);
                }
            }
          emit itemMoved();
        }
      m_oldPos = e->pos();

      update();
      e->accept();
    }
  else
    {
      e->ignore();
    }
}
コード例 #2
0
ファイル: Renderer.cpp プロジェクト: JamesLinus/dawnengine
bool Renderer::RaycastPickScreen(const Vec2& screenPosition, float depth, Camera* camera,
                                     RendererRaycastResult& result)
{
    // Set up the ray query object
    Ogre::Camera* ogreCamera = camera->GetOgreCamera();
    Ogre::Ray ray = ogreCamera->getCameraToViewportRay(screenPosition.x, screenPosition.y);
    mRaySceneQuery->setRay(ray);
    mRaySceneQuery->setQueryMask(~UNIVERSE_OBJECT);

    // Execute the ray query
    Ogre::RaySceneQueryResult& rayQuery = mRaySceneQuery->execute();
    for (auto i = rayQuery.begin(); i != rayQuery.end(); ++i)
    {
        Ogre::Entity* entity = dynamic_cast<Ogre::Entity*>((*i).movable);

        if (entity && (*i).distance > 0.0f)
        {
            result.hit = true;
            result.entity = entity;
            result.position = Position::FromCameraSpace(camera, ray.getPoint((*i).distance));
            result.normal = Vec3::zero;
            return true;
        }
    }

    // At this point - the ray didn't hit anything of interest
    result.hit = false;
    result.entity = nullptr;
    result.position = Position::FromCameraSpace(camera, ray.getPoint(depth));
    result.normal = Vec3::zero;
    return false;
}
コード例 #3
0
ファイル: PlayerController.cpp プロジェクト: Ithos/TTG
		bool CPlayerController::mousePressed(const InputListener::CMouseState &mouseState)
		{
			if(m_avatar){
				CEGUI::Vector2f mousePos = CEGUI::System::getSingleton().getDefaultGUIContext().getMouseCursor().getPosition();
				Ogre::Ray mouseRay = m_avatar->getScene()->getSceneCamera()->getCameraToViewportRay(mousePos.d_x/float(mouseState.width),mousePos.d_y/float(mouseState.height));

				float dist(1300.0f);
				 Ogre::Vector3 point = mouseRay.getPoint(Ogre::Real(dist));

                int i =0;
                while((point.y > -295.0 || point.y < -305.0) && i < 20){
					dist += 300.0 + point.y;
                    point = mouseRay.getPoint(Ogre::Real(dist));
                    i+=1;
                }
                point.y = -300.0f;

				auto it (m_mouseCommands.find(mouseState.button));
				if(it != m_mouseCommands.end()){
					m_mouseCommands[mouseState.button]->execute
						(Common::Input::Action::MOUSE_PRESSED,m_avatar,point);
					//return true; //We're not returning true because we want the mouse event to get to the GUI
				}
				
			}
			return false;
		}
コード例 #4
0
    std::pair<bool, Ogre::Vector3>
    PhysicsSystem::castRay(const Ogre::Vector3 &orig, const Ogre::Vector3 &dir, float len)
    {
        Ogre::Ray ray = Ogre::Ray(orig, dir);
        Ogre::Vector3 to = ray.getPoint(len);

        btVector3 btFrom = btVector3(orig.x, orig.y, orig.z);
        btVector3 btTo = btVector3(to.x, to.y, to.z);

        std::pair<std::string, float> test = mEngine->rayTest(btFrom, btTo);
        if (test.first == "") {
            return std::make_pair(false, Ogre::Vector3());
        }
        return std::make_pair(true, ray.getPoint(len * test.second));
    }
bool InteractiveMarkerControl::intersectSomeYzPlane( const Ogre::Ray& mouse_ray,
                                                     const Ogre::Vector3& point_on_plane,
                                                     const Ogre::Quaternion& plane_orientation,
                                                     Ogre::Vector3& intersection_3d,
                                                     Ogre::Vector2& intersection_2d,
                                                     float& ray_t )
{
  Ogre::Vector3 normal = plane_orientation * control_orientation_.xAxis();
  Ogre::Vector3 axis_1 = plane_orientation * control_orientation_.yAxis();
  Ogre::Vector3 axis_2 = plane_orientation * control_orientation_.zAxis();

  Ogre::Plane plane(normal, point_on_plane);

  Ogre::Vector2 origin_2d(point_on_plane.dotProduct(axis_1), point_on_plane.dotProduct(axis_2));

  std::pair<bool, Ogre::Real> intersection = mouse_ray.intersects(plane);
  if (intersection.first)
  {
    intersection_3d = mouse_ray.getPoint(intersection.second);
    intersection_2d = Ogre::Vector2(intersection_3d.dotProduct(axis_1), intersection_3d.dotProduct(axis_2));
    intersection_2d -= origin_2d;

    ray_t = intersection.second;
    return true;
  }

  ray_t = 0;
  return false;
}
/** Find the closest point on target_ray to mouse_ray.
 * @returns false if rays are effectively parallel, true otherwise.
 */
bool InteractiveMarkerControl::findClosestPoint( const Ogre::Ray& target_ray,
                                                 const Ogre::Ray& mouse_ray,
                                                 Ogre::Vector3& closest_point )
{
  // Find the closest point on target_ray to any point on mouse_ray.
  //
  // Math taken from http://paulbourke.net/geometry/lineline3d/
  // line P1->P2 is target_ray
  // line P3->P4 is mouse_ray

  Ogre::Vector3 v13 = target_ray.getOrigin() - mouse_ray.getOrigin();
  Ogre::Vector3 v43 = mouse_ray.getDirection();
  Ogre::Vector3 v21 = target_ray.getDirection();
  double d1343 = v13.dotProduct( v43 );
  double d4321 = v43.dotProduct( v21 );
  double d1321 = v13.dotProduct( v21 );
  double d4343 = v43.dotProduct( v43 );
  double d2121 = v21.dotProduct( v21 );

  double denom = d2121 * d4343 - d4321 * d4321;
  if( fabs( denom ) <= Ogre::Matrix3::EPSILON )
  {
    return false;
  }
  double numer = d1343 * d4321 - d1321 * d4343;

  double mua = numer / denom;
  closest_point = target_ray.getPoint( mua );
  return true;
}
コード例 #7
0
bool OgreMesh::intersectTri(const Ogre::Ray &ray, IntersectResult &rtn, Triangle*itr, bool isplane) {
    std::pair<bool, Real> hit = isplane
      ? Ogre::Math::intersects(ray, Ogre::Plane(itr->v1.coord, itr->v2.coord,itr->v3.coord))
      : Ogre::Math::intersects(ray, itr->v1.coord, itr->v2.coord,itr->v3.coord, true, false);
    rtn.u = 0;
    rtn.v = 0;
    if (hit.first && hit.second < rtn.distance) {
      rtn.intersected = hit.first;
      rtn.distance = hit.second;
      Ogre::Vector3 nml=(itr->v1.coord-itr->v2.coord).
              crossProduct(itr->v3.coord-itr->v2.coord);
      rtn.normal.x=nml.x;
      rtn.normal.y=nml.y;
      rtn.normal.z=nml.z;
      rtn.tri = *itr;
      Ogre::Vector3 intersect = ray.getPoint(hit.second) - rtn.tri.v2.coord;
      Ogre::Vector3 aVec = (rtn.tri.v1.coord - rtn.tri.v2.coord);
      Ogre::Vector3 bVec = (rtn.tri.v3.coord - rtn.tri.v2.coord);
      if (aVec.length() > 1.0e-10 && bVec.length() > 1.0e-10) {
        rtn.u = rtn.tri.v2.u + (rtn.tri.v1.u - rtn.tri.v2.u)*cos(aVec.angleBetween(intersect).valueRadians())*intersect.length()/aVec.length();
        rtn.v = rtn.tri.v2.v + (rtn.tri.v3.v - rtn.tri.v2.v)*cos(bVec.angleBetween(intersect).valueRadians())*intersect.length()/bVec.length();
      }
    }
    return rtn.intersected;
}
コード例 #8
0
ファイル: visibility.cpp プロジェクト: jstnhuang/autocp
/*
 * Heuristic method for raycasting using axis-aligned bounding boxes.
 *
 * The output of this method is the location the ray hit the first bounding box
 * belonging to the robot model or an interactive marker, where the bounding
 * boxes are sorted in order of the distance to the ray.
 *
 * This is not very accurate, and is designed to determine if the ray hits a
 * point that is "close enough" to some target point. For polygon-level
 * raytracing, see the * OGRE Wiki at goo.gl/YLKQEo.
 *
 * Input:
 *   ray: The ray to check.
 *
 * Output:
 *   hit: The median AABB point the ray hit, if any.
 *
 * Returns: True if the ray hit anything.
 */
bool VisibilityChecker::RaycastAABB(const Ogre::Ray& ray, Ogre::Vector3* hit) {
  if (!ray_scene_query_) {
    return false;
  }
  ray_scene_query_->clearResults();
  ray_scene_query_->setRay(ray);
  Ogre::RaySceneQueryResult& query_results = ray_scene_query_->execute();
  if (query_results.size() <= 0) {
    return false;
  }

  // The query results are ordered by distance along the ray. However, for some
  // reason, some of the results have zero distance. We ignore these when
  // finding the median.
  for (const auto& result : query_results) {
    auto name = result.movable->getName();
    // TODO: have the visibility checker pass in what we're looking for,
    // exactly.
    if (result.distance > 0 &&
        (name.find("Robot Link") != -1 || name.find("Shape") != -1)) {
      *hit = ray.getPoint(result.distance);
      return true;
    }
  }
  return false;
}
コード例 #9
0
ファイル: GodRaysManager.cpp プロジェクト: xDusk/lostisland04
 void GodRaysManager::_updateProjector()
 {
   const Ogre::Vector3& SunPosition = mHydrax->getSunPosition();
   const Ogre::Vector3& CameraPosition = mHydrax->getCamera()->getDerivedPosition();
   Ogre::Plane WaterPlane = Ogre::Plane(Ogre::Vector3(0, 1, 0), mHydrax->getPosition());
   Ogre::Ray SunToCameraRay = Ogre::Ray(SunPosition, CameraPosition - SunPosition);
   Ogre::Vector3 WaterProjectionPoint = SunToCameraRay.getPoint(SunToCameraRay.intersects(WaterPlane).second);
   Ogre::Vector3 WaterPosition = Ogre::Vector3(WaterProjectionPoint.x, mHydrax->getHeigth(WaterProjectionPoint), WaterProjectionPoint.z);
   mProjectorSN->setPosition(WaterProjectionPoint);
   mProjectorCamera->setFarClipDistance((WaterProjectionPoint - CameraPosition).length());
   mProjectorSN->setDirection(-(WaterProjectionPoint - CameraPosition).normalisedCopy(), Ogre::Node::TS_WORLD);
 }
コード例 #10
0
ファイル: MyFrameListener.cpp プロジェクト: flush/CEDV-2015
/*
 *Build Ray Query for getting 3d mouse position
 */
const Ogre::Vector3 MyFrameListener::getMouse3DPoint() {
  int x = _mouse->getMouseState().X.abs;
  int y = _mouse->getMouseState().Y.abs;
  Ogre::Ray ray = this->setRayQuery(x, y);

  _rayScnQueryDD->setRay(ray);
  _rayScnQueryDD->setSortByDistance(true);
  _rayScnQueryDD-> setQueryMask(PLANE_DRAG_DROP);
  Ogre::RaySceneQueryResult &result = _rayScnQueryDD->execute();
  Ogre::RaySceneQueryResult::iterator it = result.begin();
  return ray.getPoint(it->distance);
}
コード例 #11
0
ファイル: physicssystem.cpp プロジェクト: DeejStar/openmw
    std::pair<bool, Ogre::Vector3> PhysicsSystem::castRay(float mouseX, float mouseY)
    {
        Ogre::Ray ray = mRender.getCamera()->getCameraToViewportRay(
            mouseX,
            mouseY);
        Ogre::Vector3 from = ray.getOrigin();
        Ogre::Vector3 to = ray.getPoint(200); /// \todo make this distance (ray length) configurable

        btVector3 _from, _to;
        // OGRE to MW coordinates
        _from = btVector3(from.x, -from.z, from.y);
        _to = btVector3(to.x, -to.z, to.y);

        std::pair<std::string, float> result = mEngine->rayTest(_from, _to);

        if (result.first == "")
            return std::make_pair(false, Ogre::Vector3());
        else
        {
            return std::make_pair(true, ray.getPoint(200*result.second));  /// \todo make this distance (ray length) configurable
        }
    }
コード例 #12
0
ファイル: RTSState.cpp プロジェクト: xabufr/meteor-falls
std::vector<Unite *> RTSState::getUnitesInRectangleUnderCamera(const Rectangle<float> &rectangle) const
{
    Ogre::PlaneBoundedVolume vol;
    Ogre::Camera *camera = m_gameEngine->cameraManager()->camera();
    Ogre::Ray topLeft = camera->getCameraToViewportRay(rectangle.left, rectangle.top);
    Ogre::Ray topRight = camera->getCameraToViewportRay(rectangle.left + rectangle.width, rectangle.top);
    Ogre::Ray bottomLeft = camera->getCameraToViewportRay(rectangle.left, rectangle.top + rectangle.height);
    Ogre::Ray bottomRight = camera->getCameraToViewportRay(rectangle.left + rectangle.width, rectangle.top + rectangle.height);

    vol.planes.push_back(Ogre::Plane(topLeft.getPoint(1), topRight.getPoint(1), bottomRight.getPoint(1)));         // front plane
    vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), topLeft.getPoint(100), topRight.getPoint(100)));         // top plane
    vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), bottomLeft.getPoint(100), topLeft.getPoint(100)));       // left plane
    vol.planes.push_back(Ogre::Plane(bottomLeft.getOrigin(), bottomRight.getPoint(100), bottomLeft.getPoint(100)));   // bottom plane
    vol.planes.push_back(Ogre::Plane(topRight.getOrigin(), topRight.getPoint(100), bottomRight.getPoint(100)));     // right plane

    Ogre::PlaneBoundedVolumeList volList;
    volList.push_back(vol);

    EngineManager *mng = m_gameEngine->getManager();

    Ogre::PlaneBoundedVolumeListSceneQuery *query = mng->getGraphic()->getSceneManager()->createPlaneBoundedVolumeQuery(volList);
    Ogre::SceneQueryResult result = query->execute();

    std::vector<Unite *> foundUnits;
    std::for_each(result.movables.begin(), result.movables.end(), [&foundUnits](Ogre::MovableObject * obj)
    {
        try
        {
            WorldObject *worldObj = Ogre::any_cast<WorldObject *>(obj->getUserObjectBindings().getUserAny());
            Unite *unite = dynamic_cast<Unite *>(worldObj);
            foundUnits.push_back(unite);
        }
        catch (...)
        {
        }
    });

    return foundUnits;
}
コード例 #13
0
void AuthoringVisualizationCollisionDetector::testCollision(Ogre::Ray& ray, CollisionResult& result)
{
	std::pair<bool, Ogre::Real> intersectionResult(Ogre::Math::intersects(ray, mEntity.getWorldBoundingBox()));
	if (intersectionResult.first) {
		// raycast success
		result.collided = true;
		result.position = ray.getPoint(intersectionResult.second);
		result.distance = intersectionResult.second;
		result.isTransparent = true; //The authoring selector should always be transparent so that we can select things behind it
	} else {
		// raycast failed
		result.collided = false;
	}
}
コード例 #14
0
ファイル: SceneObject.cpp プロジェクト: LiberatorUSA/GUCEF
	bool SceneObject::isIntersectMesh(int& _x, int& _y, const Ogre::Ray& _ray, int _texture_width, int _texture_height) const
	{
		Ogre::Real closest_distance = -1.0f;
		Ogre::Vector3 closest_result;

		// test for hitting individual triangles on the mesh
		bool new_closest_found = false;
		int index_found = 0;
		for (int i = 0; i < static_cast<int>(mIndexCount); i += 3)
		{
			// check for a hit against this triangle
			std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(_ray, mVertices[mIndices[i]],
				mVertices[mIndices[i+1]], mVertices[mIndices[i+2]], true, false);

			// if it was a hit check if its the closest
			if (hit.first)
			{
				if ((closest_distance < 0.0f) ||
					(hit.second < closest_distance))
				{
					// this is the closest so far, save it off
					closest_distance = hit.second;
					index_found = i;
					new_closest_found = true;
				}
			}
		}

		if (new_closest_found)
		{
			closest_result = _ray.getPoint(closest_distance);

			// return the result
			if (closest_distance >= 0.0f)
			{
				// raycast success
				Ogre::Vector2 point = getCoordByTriangle(closest_result, mVertices[mIndices[index_found]], mVertices[mIndices[index_found+1]], mVertices[mIndices[index_found+2]]);
				Ogre::Vector2 point2 = getCoordByRel(point, mTextureCoords[mIndices[index_found]], mTextureCoords[mIndices[index_found+1]], mTextureCoords[mIndices[index_found+2]]);

				_x = (int)(point2.x * _texture_width);
				_y = (int)(point2.y * _texture_height);

				return true;
			}
		}

		// raycast failed
		return false;
	}
コード例 #15
0
//-----------------------------------------------------------------------
void OrthoCameraGizmo::cameraPreRenderScene (Ogre::Camera *camera)
{
	// Adjust the ortho camera gizmo
	Ogre::SceneNode* node = mOrthoCameraNodeBox->getParentSceneNode();
	if (node)
	{
		// Reposition according to the actual viewport
		Ogre::Ray ray = camera->getCameraToViewportRay(0.9f, 0.1f);
		Ogre::Vector3 position = ray.getPoint(80.0f);
		//position = camera->getDerivedOrientation().Inverse() * (position - camera->getDerivedPosition()); // Transform from world to local (camera) position
		node->setPosition(position);

		// Adjust the scale
		Ogre::Real scaleFactor = Gizmo::SCALE_NODE_ORTHOZOOM_FACTOR * camera->getOrthoWindowWidth() / camera->getViewport()->getActualWidth();
		setScale(scaleFactor);
	}
}
コード例 #16
0
bool XYOrbitViewController::intersectGroundPlane( Ogre::Ray mouse_ray, Ogre::Vector3 &intersection_3d )
{
  //convert rays into reference frame
  mouse_ray.setOrigin( target_scene_node_->convertWorldToLocalPosition( mouse_ray.getOrigin() ) );
  mouse_ray.setDirection( target_scene_node_->convertWorldToLocalOrientation( Ogre::Quaternion::IDENTITY ) * mouse_ray.getDirection() );

  Ogre::Plane ground_plane( Ogre::Vector3::UNIT_Z, 0 );

  std::pair<bool, Ogre::Real> intersection = mouse_ray.intersects(ground_plane);
  if (!intersection.first)
  {
    return false;
  }

  intersection_3d = mouse_ray.getPoint(intersection.second);
  return true;
}
コード例 #17
0
ファイル: SelectionBox.cpp プロジェクト: onze/Steel
    void SelectionBox::performSelection(std::list<AgentId> &selection, Ogre::Camera *mCamera)
    {
        if((mRight - mLeft) * (mBottom - mTop) < 0.0001)
            return;

        float left = (mLeft + 1.f) / 2.f;
        float right = (mRight + 1.f) / 2.f;
        float top = (1.f - mBottom) / 2.f;
        float bottom = (1.f - mTop) / 2.f;
        Ogre::Ray topLeft = mCamera->getCameraToViewportRay(left, top);
        Ogre::Ray topRight = mCamera->getCameraToViewportRay(right, top);
        Ogre::Ray bottomLeft = mCamera->getCameraToViewportRay(left, bottom);
        Ogre::Ray bottomRight = mCamera->getCameraToViewportRay(right, bottom);

        // These planes have now defined an "open box" which extends to infinity in front of the camera. You can think of
        // the rectangle we drew with the mouse as being the termination point of the box just in front of the camera.
        Ogre::PlaneBoundedVolume vol;
        const Ogre::Real min = .1, max = 500;
        vol.planes.push_back(Ogre::Plane(topLeft.getPoint(min), topRight.getPoint(min), bottomRight.getPoint(min)));         // front plane
        vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), topLeft.getPoint(max), topRight.getPoint(max)));         // top plane
        vol.planes.push_back(Ogre::Plane(topLeft.getOrigin(), bottomLeft.getPoint(max), topLeft.getPoint(max)));       // left plane
        vol.planes.push_back(Ogre::Plane(bottomLeft.getOrigin(), bottomRight.getPoint(max), bottomLeft.getPoint(max)));   // bottom plane
        vol.planes.push_back(Ogre::Plane(topRight.getOrigin(), topRight.getPoint(max), bottomRight.getPoint(max)));     // right plane

        Ogre::PlaneBoundedVolumeList volList;
        volList.push_back(vol);

        mVolQuery->setVolumes(volList);
        Ogre::SceneQueryResult result = mVolQuery->execute();

        // Finally we need to handle the results of the query. First we will deselect all previously selected objects,
        // then we will select all objects which were found by the query.
        std::list<Ogre::SceneNode *> nodes;
        Ogre::SceneQueryResultMovableList::iterator iter;

        for(iter = result.movables.begin(); iter != result.movables.end(); ++iter)
        {
            Ogre::MovableObject *movable = *iter;

            if(movable->getMovableType().compare("Entity") == 0)
            {
                Ogre::Entity *pentity = static_cast<Ogre::Entity *>(movable);
                nodes.push_back(pentity->getParentSceneNode());
            }
        }

        mEngine->level()->getAgentsIdsFromSceneNodes(nodes, selection);
    }
コード例 #18
0
void OgreNewtonFrameListener::dragCallback( OgreNewt::Body* me, float timestep, int threadindex )
{
	// first find the global point the mouse is at...
	CEGUI::Point mouse = CEGUI::MouseCursor::getSingleton().getPosition();
	CEGUI::Renderer* rend = CEGUI::System::getSingleton().getRenderer();
	
	Ogre::Real mx,my;
	mx = mouse.d_x / rend->getWidth();
	my = mouse.d_y / rend->getHeight();
	Ogre::Ray camray = mCamera->getCameraToViewportRay( mx, my );

	Ogre::Vector3 campt = camray.getPoint( dragDist );

	// now find the global point on the body:
	Ogre::Quaternion bodorient;
	Ogre::Vector3 bodpos;

	me->getPositionOrientation( bodpos, bodorient );

	Ogre::Vector3 bodpt = (bodorient * dragPoint) + bodpos;

	// apply the spring force!
	Ogre::Vector3 inertia;
	Ogre::Real mass;

	me->getMassMatrix( mass, inertia );

	Ogre::Vector3 dragForce = ((campt - bodpt) * mass * 8.0) - me->getVelocity();

	// draw a 3D line between these points for visual effect :)
	remove3DLine();
	mDragLine->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST );
	mDragLine->position( campt );
	mDragLine->position( bodpt );
	mDragLine->end();
	mDragLineNode->attachObject( mDragLine );


	// Add the force!
	me->addGlobalForce( dragForce, bodpt );

	Ogre::Vector3 gravity = Ogre::Vector3(0,-9.8,0) * mass;
	me->addForce( gravity );

}
コード例 #19
0
ファイル: Star.cpp プロジェクト: schobbent/SailingByTheStars
void WaterStar::followMouseRay(const Ogre::Ray& mouseRay)
{
	std::pair<bool, Real> intersectR = Math::intersects(mouseRay, *_waterPlane);
	if (intersectR.first)
	{
		Vector3 pos = mouseRay.getPoint(intersectR.second);
		/*if (pos.x < -50)
			pos.x = -50;
		if (pos.x > 50)
			pos.x = 50;
		if (pos.z > 50)
			pos.z = 50;
		if (pos.z < -50)
			pos.z = - 50;*/
		
		std::cout<< " x " << pos.x << " y " << pos.y << " z " << pos.z << std::endl;
		_node->setPosition(pos);
	}
}
コード例 #20
0
ファイル: QtWidget.cpp プロジェクト: Smiter/Ogre_editor
void OgreWidget::wheelEvent( QWheelEvent * event )
{

    mOgreWindow->getViewport(0)->getCamera()->moveRelative(Ogre::Vector3(0.0f,0.0f,event->delta() * -0.1f));
    float WindowWidth  = this->width();
    float WindowHeight = this->height();

   Ogre::Ray mouseRay = mCamera->getCameraToViewportRay((WindowWidth-60)/WindowWidth,(WindowHeight-WindowHeight+60)/WindowHeight);
   GizmoManager::getCameraGizmo()->setPosition(Ogre::Vector3(mouseRay.getPoint(mCamera->getNearClipDistance()).x,mouseRay.getPoint(mCamera->getNearClipDistance()).y,mouseRay.getPoint(mCamera->getNearClipDistance()).z));

   if(mCurrentNode)
    {

        GizmoManager::UpdateAxisSize(GizmoManager::getTranslateGizmo(),mCurrentNode,"",0);
        GizmoManager::UpdateAxisSize(GizmoManager::getRotateGizmo(),mCurrentNode,"",0);
        GizmoManager::UpdateAxisSize(GizmoManager::getScaleGizmo(),mCurrentNode,"",0);

    }  
}
コード例 #21
0
Vector3 TransformInventoryUtil::getOriginPositionPlane()
{
	Camera* player_camera = GameFramework::getSingletonPtr()->camera;
	Plane far_plane = player_camera->getFrustumPlane(1);

	float x_percent = 0.5; //((float)x / player_camera->getViewport()->getActualWidth());
	float y_percent = 0.5; //((float)y / player_camera->getViewport()->getActualHeight());

	Ogre::Ray ray = player_camera->getCameraToViewportRay(x_percent, y_percent);

	std::pair<bool, Real> result = ray.intersects(far_plane);

	if (result.first)
	{
		Vector3 origin_plane =  /*ray.getOrigin() + ray.getDirection() * 1000*/ray.getPoint(result.second * 0.9);
		return origin_plane;
	}

	return Vector3::ZERO;
}
コード例 #22
0
ファイル: Skeleton.cpp プロジェクト: dtbinh/AncelApp
bool  Skeleton::notifyMoved(const OIS::MouseEvent &evt, const Ogre::Ray &ray)
{
	if(evt.state.buttonDown(OIS::MB_Left))
	{
		Ogre::Vector3 shift = ray.getPoint(mCollsionDepth);
		
		shift -= mPressedPosition;
		
		//pos 
		if(AnimationEditorPanel::getSingletonPtr()->isFixXAxis()) shift.x = 0;
		if(AnimationEditorPanel::getSingletonPtr()->isFixYAxis()) shift.y = 0;
		if(AnimationEditorPanel::getSingletonPtr()->isFixZAxis()) shift.z = 0;
 		
		mPressedPosition += shift;

		AnimationEditor* editor = static_cast<AnimationEditor*>(mPickEventHandle);
		editor->updateShiftValue(shift);
	}
 	return true;
}
コード例 #23
0
ファイル: SceneEntity.cpp プロジェクト: dtbinh/AncelApp
bool SceneEntity::notifyMoved(const OIS::MouseEvent &evt, const Ogre::Ray &ray)
{
	if(evt.state.buttonDown(OIS::MB_Left))
	{
		Ogre::Vector3 position = ray.getPoint(mCollsionDepth) + mPickedNodeOffset;
		Ogre::Vector3 pos = position - mSceneNode->getPosition();

		float dis = pos.length();
		if(dis < 500)
		{
			if(mIsXFixed) position.x = mSceneNode->getPosition().x;
			if(mIsYFixed) position.y = mSceneNode->getPosition().y;
			if(mIsZFixed) position.z = mSceneNode->getPosition().z;
 
			mSceneNode->setPosition(position);
			AxisEntity::getSingletonPtr()->setPosition(position);
			AxisEntity::getSingletonPtr()->setVisible(true);
		}
	}
	return true;
}
コード例 #24
0
void ClientGame::UpdateTileUnderCursor(Ogre::Ray aRay)
{
    Ogre::Real radius = mTiles[0]->GetPosition().length();
    Ogre::Sphere sphere(Ogre::Vector3::ZERO, radius);
    std::pair<bool, Ogre::Real> res = aRay.intersects(sphere);
    if (res.first)
    {
        Ogre::Vector3 position(aRay.getPoint(res.second));
        mTileUnderCursor = mTileUnderCursor->GetTileAtPosition(position);
        if (mSelectionMarker->getParent())
        {
            mSelectionMarker->getParent()->removeChild(mSelectionMarker);
        }

        if (mTileUnderCursor->GetTile())
        {
            mTileUnderCursor->GetTile()->GetNode().addChild(mSelectionMarker);
        }

    }
    mSelectionMarker->setVisible(res.first);
}
コード例 #25
0
ファイル: QtWidget.cpp プロジェクト: Smiter/Ogre_editor
void OgreWidget::CameraLooking(float x, float y, float currentX, float currentY)
{
    float deltaX=currentX-x;
    float deltaY=currentY-y;

    if(x<currentX)
    {
           mCamera->yaw(Ogre::Radian(deltaX) * 0.006f);
           GizmoManager::getCameraGizmo()->NodeCameraGizmoSupport->rotate( Ogre::Vector3::UNIT_Y,Ogre::Radian(deltaX) * 0.006f, Ogre::Node::TS_PARENT);
           GizmoManager::getCameraGizmo()->Rotate( Ogre::Vector3::UNIT_Y,Ogre::Radian(-deltaX) * 0.006f, Ogre::Node::TS_LOCAL);
    }
    else
    {
          mCamera->yaw(Ogre::Radian(deltaX) * 0.006f);
          GizmoManager::getCameraGizmo()->NodeCameraGizmoSupport->rotate( Ogre::Vector3::UNIT_Y,Ogre::Radian(deltaX) * 0.006f, Ogre::Node::TS_PARENT);
          GizmoManager::getCameraGizmo()->Rotate( Ogre::Vector3::UNIT_Y,Ogre::Radian(-deltaX) * 0.006f, Ogre::Node::TS_LOCAL);
    }

    if(y<currentY)
    {
          mCamera->pitch(Ogre::Radian(deltaY) * 0.006f);
          GizmoManager::getCameraGizmo()->NodeCameraGizmoSupport->rotate( mCamera->getRealOrientation()*Ogre::Vector3(1,0,0),Ogre::Radian(deltaY) * 0.006f, Ogre::Node::TS_PARENT);
          GizmoManager::getCameraGizmo()->Rotate( mCamera->getRealOrientation()*Ogre::Vector3(1,0,0),Ogre::Radian(-deltaY) * 0.006f, Ogre::Node::TS_PARENT);

    }
    else
    {
           mCamera->pitch(Ogre::Radian(deltaY) * 0.006f);
           GizmoManager::getCameraGizmo()->NodeCameraGizmoSupport->rotate( mCamera->getRealOrientation()*Ogre::Vector3(1,0,0),Ogre::Radian(deltaY) * 0.006f, Ogre::Node::TS_PARENT);
           GizmoManager::getCameraGizmo()->Rotate( mCamera->getRealOrientation()*Ogre::Vector3(1,0,0),Ogre::Radian(-deltaY) * 0.006f, Ogre::Node::TS_PARENT);
    }
    float WindowWidth  = this->width();
    float WindowHeight = this->height();
    Ogre::Ray mouseRay = mCamera->getCameraToViewportRay((WindowWidth-60)/WindowWidth,(WindowHeight-WindowHeight+60)/WindowHeight);
    GizmoManager::getCameraGizmo()->setPosition(Ogre::Vector3(mouseRay.getPoint(mCamera->getNearClipDistance()).x,mouseRay.getPoint(mCamera->getNearClipDistance()).y,mouseRay.getPoint(mCamera->getNearClipDistance()).z));

}
コード例 #26
0
ファイル: Ground.cpp プロジェクト: agruzdev/OgreNature
//-------------------------------------------------------
std::pair<bool, Ogre::Vector3> Ground::GetIntersectionLocalSpace(const Ogre::Ray & ray) const
{
    if (ray.intersects(mGlobalBoundingBox).first)
    {
        float intersection = -1.0f;
        for (const auto & region : mEntities)
        {
            auto hit = ray.intersects(region->getBoundingBox());
            if (hit.first)
            {
                auto meshHit = GetVertexIntersection(ray, region->getMesh()->getSubMesh(0));
                if (meshHit.first && (intersection < 0.0f || meshHit.second < intersection))
                {
                    intersection = meshHit.second;
                }
            }
        }
        if (intersection >= 0.0f)
        {
            return std::make_pair(true, ray.getPoint(intersection));
        }
    }
    return std::make_pair(false, Ogre::Vector3::ZERO);
}
コード例 #27
0
ファイル: ogrewidget.cpp プロジェクト: wpfhtl/octocopter
void OgreWidget::paintEvent(QPaintEvent* event)
{
//    qDebug() << __PRETTY_FUNCTION__;

    if(!mOgreRenderWindow)
    {
        initializeOgre();
    }

    QMutexLocker locker(&mMutex);
    if(!mOgreRoot) initializeOgre();

    if(mTerrainGroup->isDerivedDataUpdateInProgress())
    {
        if(mTerrainsImported)
        {
            qDebug() << "OgreWidget::paintEvent(): DerivedDataUpdateInProgress, building terrain, please wait";
            mSimulator->statusBar()->showMessage("Building terrain, please wait...");
        }
        else
        {
            qDebug() << "OgreWidget::paintEvent(): DerivedDataUpdateInProgress, updating textures, please wait";
            mSimulator->statusBar()->showMessage("Updating textures, patience...");
        }
    }
    else
    {
        if(mTerrainsImported)
        {
            qDebug() << "OgreWidget::paintEvent(): saving terrains    ";
            mSimulator->statusBar()->showMessage("Saving all terrains.");
            mTerrainGroup->saveAllTerrains(true);
            mTerrainsImported = false;
            //mSimulator->statusBar()->hide();
        }
    }

    mOgreRoot->_fireFrameStarted();

    // this should be IN a frame listener! animation currently unused
    //    if(mVehicleAnimationState) mVehicleAnimationState->addTime(0.1);

    //    qDebug() << "now rendering";

    // Construct all laserscanner rays before rendering
    QList<LaserScanner*> *laserScanners = mSimulator->mLaserScanners;
    for(int i = 0; i < laserScanners->size(); ++i)
    {
        LaserScanner* scanner = laserScanners->at(i);
        Ogre::Ray beam = scanner->getCurrentLaserBeam();

        Q_ASSERT(scanner->getSceneNode()->getParent() == mVehicleNode);

        //        scanner->getSceneNode()->_update(false, true);

        scanner->mRayObject->clear();

        if(scanner->isScanning())
        {
            scanner->mRayObject->begin(QString("RayFrom_" + scanner->objectName() + "_material").toStdString(), Ogre::RenderOperation::OT_LINE_LIST);
            //        scanner->mRayObject->position(mVehicleNode->_getDerivedPosition() + mVehicleNode->getOrientation() * scanner->getSceneNode()->getPosition());
            scanner->mRayObject->position(scanner->getSceneNode()->_getDerivedPosition());
            //        scanner->mRayObject->position(beam.getPoint(0.0));
            scanner->mRayObject->position(beam.getPoint(scanner->range()));
            scanner->mRayObject->end();
        }
    }

    mOgreRenderWindow->update();
    //    qDebug() << "rendering done";

    mOgreRoot->_fireFrameEnded();

    if(mFrameCount++ % 25 == 0)
        emit currentRenderStatistics(size(), mOgreRenderWindow->getTriangleCount(), mOgreRenderWindow->getLastFPS());

    event->accept();
}
コード例 #28
0
ファイル: CollisionTools.cpp プロジェクト: aerique/okra
bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask)
{
	target = NULL;

    // check we are initialised
    if (mRaySceneQuery != NULL)
    {
        // create a query object
        mRaySceneQuery->setRay(ray);
		mRaySceneQuery->setSortByDistance(true);
		mRaySceneQuery->setQueryMask(queryMask);
        // execute the query, returns a vector of hits
        if (mRaySceneQuery->execute().size() <= 0)
        {
            // raycast did not hit an objects bounding box
            return (false);
        }
    }
    else
    {
        //LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG;
        return (false);
    }

    // at this point we have raycast to a series of different objects bounding boxes.
    // we need to test these different objects to see which is the first polygon hit.
    // there are some minor optimizations (distance based) that mean we wont have to
    // check all of the objects most of the time, but the worst case scenario is that
    // we need to test every triangle of every object.
    //Ogre::Ogre::Real closest_distance = -1.0f;
	closest_distance = -1.0f;
    Ogre::Vector3 closest_result;
    Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults();
    for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
    {
        // stop checking if we have found a raycast hit that is closer
        // than all remaining entities
        if ((closest_distance >= 0.0f) &&
            (closest_distance < query_result[qr_idx].distance))
        {
            break;
        }

        // Only check this result if its a hit against an Entity or
        // ManualObject.
        if ((query_result[qr_idx].movable != NULL) &&
            (query_result[qr_idx].movable->isVisible()) &&
            ((query_result[qr_idx].movable->getMovableType().compare("Entity") == 0) ||
             (query_result[qr_idx].movable->getMovableType().compare("ManualObject") == 0)))
        {
            // get the entity to check
            Ogre::MovableObject *pmovable =
               static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable);

            Ogre::MeshPtr mesh_ptr;

            if (query_result[qr_idx].movable->getMovableType().compare("Entity") == 0)
            {
                mesh_ptr = ((Ogre::Entity*)pmovable)->getMesh();
            }
            else
            {
                // XXX: Does "Mesh" get replaced so we can get away with not
                // XXX: deleting it for now?
                mesh_ptr = ((Ogre::ManualObject*)pmovable)->convertToMesh("Mesh", "General");
            }

            // mesh data to retrieve
            size_t vertex_count;
            size_t index_count;
            Ogre::Vector3 *vertices;
            Ogre::uint32 *indices;

            // get the mesh information
            GetMeshInformation(mesh_ptr, vertex_count, vertices, index_count, indices, pmovable->getParentNode()->_getDerivedPosition(), pmovable->getParentNode()->_getDerivedOrientation(), pmovable->getParentNode()->_getDerivedScale());

            // test for hitting individual triangles on the mesh
            bool new_closest_found = false;
            for (size_t i = 0; i < index_count; i += 3)
            {
                // check for a hit against this triangle
                std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
                    vertices[indices[i+1]], vertices[indices[i+2]], true, false);

                // if it was a hit check if its the closest
                if (hit.first)
                {
                    if ((closest_distance < 0.0f) ||
                        (hit.second < closest_distance))
                    {
                        // this is the closest so far, save it off
                        closest_distance = hit.second;
                        new_closest_found = true;
                    }
                }
            }

            // free the verticies and indicies memory
            delete[] vertices;
            delete[] indices;

            // if we found a new closest raycast for this object, update the
            // closest_result before moving on to the next object.
            if (new_closest_found)
            {
                target = pmovable;
                closest_result = ray.getPoint(closest_distance);
            }
        }
    }

    // return the result
    if (closest_distance >= 0.0f)
    {
        // raycast success
        result = closest_result;
        return (true);
    }
    else
    {
        // raycast failed
        return (false);
    }
}
コード例 #29
0
	bool CollisionTools::raycast(const Ogre::Ray &ray, Ogre::Vector3 &result,Ogre::MovableObject* &target,float &closest_distance, const Ogre::uint32 queryMask)
	{
		target = NULL;

		// check we are initialised
		if (mRaySceneQuery != NULL)
		{
			// create a query object
			mRaySceneQuery->setRay(ray);
			mRaySceneQuery->setSortByDistance(true);
			mRaySceneQuery->setQueryMask(queryMask);
			// execute the query, returns a vector of hits
			if (mRaySceneQuery->execute().size() <= 0)
			{
				// raycast did not hit an objects bounding box
				return (false);
			}
		}
		else
		{
			//LOG_ERROR << "Cannot raycast without RaySceneQuery instance" << ENDLOG;
			return (false);
		}

		// at this point we have raycast to a series of different objects bounding boxes.
		// we need to test these different objects to see which is the first polygon hit.
		// there are some minor optimizations (distance based) that mean we wont have to
		// check all of the objects most of the time, but the worst case scenario is that
		// we need to test every triangle of every object.
		//Ogre::Ogre::Real closest_distance = -1.0f;
		closest_distance = -1.0f;
		Ogre::Vector3 closest_result;
		Ogre::RaySceneQueryResult &query_result = mRaySceneQuery->getLastResults();

#if 0
		for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
		{
			const Ogre::RaySceneQueryResultEntry& result = query_result[qr_idx];
			Ogre::Real distance = result.distance;
			Ogre::MovableObject* movable = static_cast<Ogre::MovableObject*>(result.movable);
			Ogre::SceneQuery::WorldFragment* worldFragment = result.worldFragment;

			if (movable)
			{
				const Ogre::String& type = movable->getMovableType();
				const Ogre::String& name = movable->getName();
				const Ogre::String& parentName = movable->getParentNode()->getName();
				Ogre::uint32 flag = movable->getQueryFlags();  

				if (type.compare("Entity") == 0)
				{
					Ogre::Entity* ent =  (Ogre::Entity*)movable;
				}

				std::ostrstream oss;
				oss<<"name:"<<name<<" distance:"<< distance <<" type:"<<type<<" flag:"<<flag<<" parent:"<<parentName<<std::endl;
				OutputDebugString(oss.str() );
			}
		}

#endif

		for (size_t qr_idx = 0; qr_idx < query_result.size(); qr_idx++)
		{
			// stop checking if we have found a raycast hit that is closer
			// than all remaining entities
			if ((closest_distance >= 0.0f) &&
				(closest_distance < query_result[qr_idx].distance))
			{
				break;
			}

			// only check this result if its a hit against an entity
			if ((query_result[qr_idx].movable != NULL)  &&
				(query_result[qr_idx].movable->getMovableType().compare("Entity") == 0))
			{
				// get the entity to check
				Ogre::MovableObject *pentity = static_cast<Ogre::MovableObject*>(query_result[qr_idx].movable);

				// mesh data to retrieve
				size_t vertex_count;
				size_t index_count;
				Ogre::Vector3 *vertices = NULL;
				Ogre::uint32 *indices = NULL;

				// get the mesh information
				GetMeshInformation(((Ogre::Entity*)pentity)->getMesh(), vertex_count, vertices, index_count, indices,
					pentity->getParentNode()->_getDerivedPosition(),
					pentity->getParentNode()->_getDerivedOrientation(),
					pentity->getParentNode()->_getDerivedScale());

				// test for hitting individual triangles on the mesh
				bool new_closest_found = false;
				for (size_t i = 0; i < index_count; i += 3)
				{
					// check for a hit against this triangle
					std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]],
						vertices[indices[i+1]], vertices[indices[i+2]], true, false);

					// if it was a hit check if its the closest
					if (hit.first)
					{
						if ((closest_distance < 0.0f) ||
							(hit.second < closest_distance))
						{
							// this is the closest so far, save it off
							closest_distance = hit.second;
							new_closest_found = true;
						}
					}
				}

				// free the verticies and indicies memory
				delete  vertices;
				delete  indices;

				// if we found a new closest raycast for this object, update the
				// closest_result before moving on to the next object.
				if (new_closest_found)
				{
					target = pentity;
					closest_result = ray.getPoint(closest_distance);
				}
			}
		}

		// return the result
		if (closest_distance >= 0.0f)
		{
			// raycast success
			result = closest_result;
			return (true);
		}
		else
		{
			// raycast failed
			return (false);
		}
	}
コード例 #30
0
ファイル: HeadsUpDisplay.cpp プロジェクト: eblock12/stuff
void HeadsUpDisplay::tick(Ogre::Real timeDelta)
{
    // window dimensions may have changed
    Application &app = Application::getSingleton();
    Ogre::Real windowWidth = (Ogre::Real)app.getWindowWidth();
    Ogre::Real windowHeight = (Ogre::Real)app.getWindowHeight();

    // get mouse cursor and update absolute position from relative change
    OIS::Mouse *mouse = app.getMouse();
    if (mouse != nullptr)
    {
        OIS::MouseState mouseState = mouse->getMouseState();
        m_cursorX += mouseState.X.rel;
        m_cursorY += mouseState.Y.rel;
        m_cursorX = Math::clamp(m_cursorX, 0, windowWidth);
        m_cursorY = Math::clamp(m_cursorY, 0, windowHeight);

        // normalize cursor position and size from 0 to 1
        Ogre::Real cursorX = m_cursorX / windowWidth;
        Ogre::Real cursorY = m_cursorY / windowHeight;
        m_cursorContainer->setPosition(cursorX, cursorY);
        m_cursorContainer->setWidth(CURSOR_WIDTH / windowWidth);
        m_cursorContainer->setHeight(CURSOR_HEIGHT / windowHeight);
        m_cursorContainer->show();

        // project cursor ray into scene and get query results
        if (!m_mouseLeftLastDown && mouseState.buttonDown(OIS::MouseButtonID::MB_Left))
        {
            Ogre::Ray mouseRay;
            getCamera()->getCameraToViewportRay(cursorX, cursorY, &mouseRay);
            m_rayQuery->setRay(mouseRay);
            m_objectFound = false;
            m_rayQuery->execute(this);

            if (!m_objectFound && (m_currentSelection != nullptr))
            {
                // user selected nothing so clear current selection
                m_currentSelection->onDeselect();
            }
        }

        if ((m_currentSelection != nullptr) && !m_mouseRightLastDown && mouseState.buttonDown(OIS::MouseButtonID::MB_Right))
        {
            Ogre::Ray mouseRay;
            getCamera()->getCameraToViewportRay(cursorX, cursorY, &mouseRay);
            Ogre::Plane plane(Ogre::Vector3(0, 1, 0), Ogre::Vector3::ZERO);
            auto intersectResult = mouseRay.intersects(plane);
            if (intersectResult.first)
            {
                Ogre::Vector3 destination = mouseRay.getPoint(intersectResult.second);
                m_currentSelection->onMoveOrder(destination);
            }
        }
        
        m_mouseLeftLastDown = mouseState.buttonDown(OIS::MouseButtonID::MB_Left);
        m_mouseRightLastDown = mouseState.buttonDown(OIS::MouseButtonID::MB_Right);
    }
    else
    {
        m_cursorContainer->hide();
    }
}