Ejemplo n.º 1
0
		void GizmoAxis::Update(Urho3D::Ray cameraRay, float scale, bool drag, const Urho3D::Vector3& camPos)
		{
			Urho3D::UI* ui = GetSubsystem<Urho3D::UI>();

			// Do not select when UI has modal element
			if (ui->HasModalElement())
			{
				selected = false;
				return;
			}

			Urho3D::Vector3 closest = cameraRay.ClosestPoint(axisRay);
			Urho3D::Vector3 projected = axisRay.Project(closest);
			d = axisRay.Distance(closest);
			t = (projected - axisRay.origin_).DotProduct(axisRay.direction_);

			// Determine the sign of d from a plane that goes through the camera position to the axis
			Urho3D::Plane axisPlane(camPos, axisRay.origin_, axisRay.origin_ + axisRay.direction_);
			if (axisPlane.Distance(closest) < 0.0)
				d = -d;

			// Update selected status only when not dragging
			if (!drag)
			{
				selected = (Urho3D::Abs(d) < axisMaxD * scale) && (t >= -axisMaxD * scale) && (t <= axisMaxT * scale);
				lastT = t;
				lastD = d;
			}
		}
Ejemplo n.º 2
0
// yes, I realize this breaks on caps when the ray origin is inside the cylinder.
// it's not like it's actually going to be in there anyway.
BOOL CylinderRayCollision(const Vect &center, float radius, float height, const Vect &rayOrig, const Vect &rayDir, Vect *collision, Plane *collisionPlane)
{
    Vect collisionValue;
    BOOL bHit = FALSE;
    float fT;

    Plane axisPlane(0.0f, 1.0f, 0.0f, center.y);

    //---------------------------------------
    // test the cap
    if(fabs(rayDir.y) > EPSILON)
    {
        BOOL bUnder = (rayDir.y<0.0f);

        Plane planeCap;
        planeCap.Dir.Set(0.0f, bUnder ? 1.0f : -1.0f, 0.0f);
        planeCap.Dist = (bUnder ? center.y : -center.y)+height;

        if(rayOrig.DistFromPlane(planeCap) > 0.0f)
        {
            if(planeCap.GetRayIntersection(rayOrig, rayDir, fT))
            {
                collisionValue = rayOrig+(rayDir*fT);
                Vect CapCenter = center+(planeCap.Dir*height);

                if(collisionValue.Dist(CapCenter) <= radius)
                {
                    if(collisionPlane)
                        *collisionPlane = planeCap;
                    bHit = TRUE;
                }
            }
        }
    }

    if(!bHit && ((1.0f-fabs(rayDir.y)) > EPSILON))
    {
        //---------------------------------------
        // test the body
        Vect adjDir, adjCenter;

        adjDir.Set(rayDir.x, 0.0f, rayDir.z).Norm();
        adjCenter.Set(center.x, rayOrig.y, center.z);

        Vect l   = (adjCenter-rayOrig);
        float d  = l | adjDir;          //distance from adjDir Plane
        float l2 = l | l;               //c-o distance squared
        float r2 = radius*radius;

        if(l2 < r2)                     //if inside the cylinder, fail
            return FALSE;

        if((d < 0.0f) && (l2 > r2))     //if the plane distance is negative, and
            return FALSE;               //the distance is over the radius, fail

        float m2 = l2 - (d*d);          //distance from the cylinder center to
                                        //the closest ray point

        if(m2 > r2)                     //if m2 is larger than the radius, fail
            return FALSE;

        float q = sqrt(r2-m2);          //real distance from the edge of the
                                        //cylinder to the cloest ray point
                                        //(forms a sort of triangle)

        fT = (l2 > r2) ? (d-q) : (d+q); //if the distance is over the radius,
                                        //d-q = T, else d+q=T
                                        //distance

        fT /= (adjDir|rayDir);          //divide by angle to get the proper
                                        //value

        collisionValue = rayOrig+(rayDir*fT);

        if(fabs(collisionValue.DistFromPlane(axisPlane)) >= height)
            return FALSE;

        if(collisionPlane)
        {
            Vect temp = collisionValue;
            temp.y = center.y;

            collisionPlane->Dir  = (temp-center).Norm();
            collisionPlane->Dist = collisionPlane->Dir|temp;
        }

        bHit = TRUE;
    }

    if(!bHit)
        return FALSE;

    if(collision)
        *collision = collisionValue;

    return TRUE;
}