Esempio n. 1
0
	//-------------------------------------------------------------------
	void ICamera::PickRay(const vector2f& secen, Rayf& out)
	{
		//if( m_isChange )
		//{
		//	Update();
		//}
		//http://stackoverflow.com/questions/2093096/implementing-ray-picking
		//First you need to determine where on the nearplane the mouse click happened:
		//
		//rescale the window coordinates (0..640,0..480) to [-1,1], with (-1,-1) at the bottom-left corner and (1,1) at the top-right.
		//'undo' the projection by multiplying the scaled coordinates by what I call the 'unview' matrix: unview = (P * M).inverse() = M.inverse() * P.inverse(), where M is the ModelView matrix and P is the projection matrix.
		//Then determine where the camera is in worldspace, and draw a ray starting at the camera and passing through the point you found on the nearplane.
		//
		//The camera is at M.inverse().col(4), i.e. the final column of the inverse ModelView matrix.
		//
		//Final pseudocode:
		//
		//normalised_x = 2 * mouse_x / win_width - 1
		//normalised_y = 1 - 2 * mouse_y / win_height
		//// note the y pos is inverted, so +y is at the top of the screen
		//
		//unviewMat = (projectionMat * modelViewMat).inverse()
		//
		//near_point = unviewMat * Vec(normalised_x, normalised_y, 0, 1)
		//camera_pos = ray_origin = modelViewMat.inverse().col(4)
		//ray_dir = near_point - camera_pos


		//vector4f ray(secen.m_x, secen.m_y , 1.0 , 1.0 );
		////ray *= (*m_pUnProject);//这两部等效于ray *= ( (*m_pUnProject) * (*m_pUnView) );
		////ray *= (*m_pUnView);
		//ray *= m_UnViewProject;
		//ray /= ray.m_w;
		////vector4f camera(m_pUnView->a41,m_pUnView->a42,m_pUnView->a43,m_pUnView->a44);
		////camera /= camera->m_w;
		////ray -= camera;
		//ray -= vector4f( m_Position );

		//vector3f reslut(ray.m_x, ray.m_y, ray.m_z);
		//reslut.NormalizeSelf();
		//out.m_RayOrig = m_Position;
		//out.m_RayDir = reslut;

		vector4f rayb(secen.m_x, secen.m_y , 0.0 , 1.0 );//理论上z这个值应该是0,但是这样算出来的Y值偏小和aabb射线拾取不统一,故该做-1,只放大初始位置
		vector4f raye(secen.m_x, secen.m_y , 1.0 , 1.0 );
		vector4f ray2;
		rayb *= GetUnViewProj();
		ASSERT( 0 != rayb.m_w );
		rayb /= rayb.m_w;
		raye *= GetUnViewProj();
		ASSERT( 0 != raye.m_w );
		raye /= raye.m_w;

		ray2 = raye - rayb;
		vector3f reslut2(ray2.m_x, ray2.m_y, ray2.m_z);
		reslut2.NormalizeSelf();
		out.SetRayOrigin( vector3f(rayb) );
		out.SetRayDirection( reslut2 );
	}
Esempio n. 2
0
 void Entity::pick(const Rayf& ray, PickResult& pickResults) {
     float dist = bounds().intersectWithRay(ray, NULL);
     if (Math<float>::isnan(dist))
         return;
     
     Vec3f hitPoint = ray.pointAtDistance(dist);
     EntityHit* hit = new EntityHit(*this, hitPoint, dist);
     pickResults.add(hit);
 }
Esempio n. 3
0
 Vec3f Grid::moveDeltaForBounds(const Model::Face& face, const BBoxf& bounds, const BBoxf& worldBounds, const Rayf& ray, const Vec3f& position) const {
     const Planef dragPlane = Planef::alignedOrthogonalDragPlane(position, face.boundary().normal);
     
     const Vec3f halfSize = bounds.size() * 0.5f;
     float offsetLength = halfSize.dot(dragPlane.normal);
     if (offsetLength < 0.0f)
         offsetLength *= -1.0f;
     const Vec3f offset = dragPlane.normal * offsetLength;
     
     const float dist = dragPlane.intersectWithRay(ray);
     const Vec3f newPos = ray.pointAtDistance(dist);
     Vec3f delta = moveDeltaForPoint(bounds.center(), worldBounds, newPos - (bounds.center() - offset));
     
     Axis::Type a = dragPlane.normal.firstComponent();
     if (dragPlane.normal[a] > 0.0f) delta[a] = position[a] - bounds.min[a];
     else delta[a] = position[a] - bounds.max[a];
     
     return delta;
 }
Esempio n. 4
0
        void Brush::pick(const Rayf& ray, PickResult& pickResults) {
            float dist = bounds().intersectWithRay(ray, NULL);
            if (Math<float>::isnan(dist))
                return;

            dist = Math<float>::nan();
            Side* side = NULL;
            for (unsigned int i = 0; i < m_geometry->sides.size() && Math<float>::isnan(dist); i++) {
                side = m_geometry->sides[i];
                dist = side->intersectWithRay(ray);
            }

            if (!Math<float>::isnan(dist)) {
                assert(side != NULL);
                Vec3f hitPoint = ray.pointAtDistance(dist);
                FaceHit* hit = new FaceHit(*(side->face), hitPoint, dist);
                pickResults.add(hit);
            }
        }
Esempio n. 5
0
//------------------------------------------------------------------------------
//!
bool
BIH::trace( const Rayf& ray, Hit& hit, IntersectFunc intersect, void* data ) const
{
   DBG_BLOCK( os_bih_trace, "BIH::trace(" << ray.origin() << ray.direction() << " hit: t=" << hit._t << " id=" << hit._id << ")" );
   if( _nodes.empty() )
   {
      return false;
   }

   Vec3f invDir = ray.direction().getInversed(); 

   // Compute traversal order.
   uint order[3];
   order[0] = invDir(0) >= 0.0f ? 0 : 1;
   order[1] = invDir(1) >= 0.0f ? 0 : 1;
   order[2] = invDir(2) >= 0.0f ? 0 : 1;

   float tmin  = 0.0f;
   float tmax  = hit._t;
   bool impact = false;


   // Traverse tree.
   Vector<TraversalStackNode> stack( _maxDepth );
   uint stackID = 0;
   const Node* node = &_nodes[0];

   while( 1 )
   {
      DBG_MSG( os_bih_trace, "Visiting " << *node );
      if( node->isInteriorNode() )
      {
         uint axis     = node->axis();
         float tplane0 = ( node->_plane[order[axis]] - ray.origin()(axis)) * invDir(axis);
         float tplane1 = ( node->_plane[1-order[axis]] - ray.origin()(axis)) * invDir(axis);

         // Clip node.
         if( node->isClipNode() )
         {
            // FIXME: we could probably do better (not traversing this node).
            node = &_nodes[node->index()];
            tmin = CGM::max( tmin, tplane0 );
            tmax = CGM::min( tmax, tplane1 );
            continue;
         }

         bool traverse0 = tmin < tplane0;
         bool traverse1 = tmax > tplane1;

         if( traverse0 )
         {
            if( traverse1 )
            {
               stack[stackID++].set(
                  &_nodes[node->index() + 1-order[axis]],
                  CGM::max( tmin, tplane1 ),
                  tmax
               );
            }
            node = &_nodes[node->index() + order[axis]];
            tmax = CGM::min( tmax, tplane0 );
         }
         else
         {
            if( traverse1 )
            {
               node = &_nodes[node->index() + 1-order[axis]];
               tmin = CGM::max( tmin, tplane1 );
            }
            else
            {
               // Unstack.
               do
               {
                  if( stackID == 0 )
                  {
                     return impact;
                  }
                  stack[--stackID].get( node, tmin, tmax );
                  tmax = CGM::min( tmax, hit._t );
               } while( tmin > tmax );
            }
         }

      }
      else
      {
         // We are in a leaf node.
         // Intersects all primitives in it.
         uint numElems = node->_numElements;
         uint id       = node->index();
         for( uint i = 0; i < numElems; ++i, ++id )
         {
            if( intersect( ray, _ids[id], hit._t, data ) )
            {
               impact  = true;
               hit._id = _ids[id];
            }
         }

         // Unstack.
         do
         {
            if( stackID == 0 )
            {
               return impact;
            }
            stack[--stackID].get( node, tmin, tmax );
            tmax = CGM::min( tmax, hit._t );
         } while( tmin > tmax );
      }
   }
}
Esempio n. 6
0
	//------------------------------------------------------------------------------------------------------
	SelectableRotatingRing::Selected SelectableRotatingRing::IsSelected( const Rayf& r )
	{
		aabbox3df local = m_BindBox;
		local.SetCenter( GetWorldPosition() );
		m_XBind.SetCenter( GetWorldPosition() );
		m_YBind.SetCenter( GetWorldPosition() );
		m_ZBind.SetCenter( GetWorldPosition() );
		if ( ( local ).Intersection( r ) )
		{
			std::map< float, SelectableRotatingRing::Selected > rm;
			vector3f point;
			if(( m_XBind ).IntersectPointWithRay( r, point ) ) rm.insert( std::make_pair( (point - r.GetRayOrigin()).LengthPow(), SR_BY_X_AXIS ) );
			if(( m_YBind ).IntersectPointWithRay( r, point ) ) rm.insert( std::make_pair( (point - r.GetRayOrigin()).LengthPow(), SR_BY_Y_AXIS ) );
			if(( m_ZBind ).IntersectPointWithRay( r, point ) ) rm.insert( std::make_pair( (point - r.GetRayOrigin()).LengthPow(), SR_BY_Z_AXIS ) );
			if ( rm.empty() )
			{
				return SR_NON;
			}
			return rm.begin()->second;
		}
		return SR_NON;
	}