Exemplo n.º 1
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);
 }
Exemplo n.º 2
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);
            }
        }
Exemplo n.º 3
0
void PhysicsWorld::Pick(const Math::Vector3 &pos, PickResult &result)
{
	Broadphase::PickResult colliders;
	mBroadphase->Pick(pos, colliders);

	// clear pick flags
	for (auto collider : colliders)
	{
		auto &body = *collider->mParent;
		body.mFlags.Clear(PhysicsFlags::PICK);
	}

	// compute result
	for (auto collider : colliders)
	{
		auto &body = *collider->mParent;
		if (!body.mFlags.Test(PhysicsFlags::PICK) && collider->CollidesCollider(pos))
		{
			body.mFlags.Set(PhysicsFlags::PICK);
			result.push_back(&body);
		}
	} // end of collider loop
}
/** Determine the closest object intersected by a ray given by the pick origin and direction.
  * This method returns true if any object was intersected. If the value of result is not
  * null, it will be updated with information about which object was hit by the pick ray.
  *
  * @param t The time given as the number of seconds since 1 Jan 2000 12:00:00 UTC.
  * @param pickOrigin origin of the pick ray
  * @param pickDirection direction of the pick ray (does not need to be normalized)
  * @param pixelAngle angle in radians subtended by a pixel
  * @param result pointer to a PickResult object that will be filled in if the pick ray
  *    hits something.
  */
bool
Universe::pickObject(double t,
                     const Vector3d& pickOrigin,
                     const Vector3d& pickDirection,
                     double pixelAngle,
                     PickResult* result) const
{
    double closest = numeric_limits<double>::infinity();
    PickResult closestResult;

    for (EntityTable::const_iterator iter = m_entities.begin(); iter != m_entities.end(); ++iter)
    {
        Entity* entity = iter->ptr();

        if (entity->geometry() || entity->hasVisualizers())
        {
            if (entity->isVisible() && entity->chronology()->includesTime(t))
            {
                Vector3d position = entity->position(t);

                if (entity->geometry())
                {
                    Geometry* geometry = entity->geometry();
                    double intersectionDistance;
                    if (TestRaySphereIntersection(pickOrigin,
                                                  pickDirection,
                                                  position,
                                                  geometry->boundingSphereRadius(),
                                                  &intersectionDistance))
                    {
                        if (intersectionDistance < closest)
                        {
                            // Transform the pick ray into the local coordinate system of body
                            Matrix3d invRotation = entity->orientation(t).conjugate().toRotationMatrix();
                            Vector3d relativePickOrigin = invRotation * (pickOrigin - position);
                            Vector3d relativePickDirection = invRotation * pickDirection;

                            double distance = intersectionDistance;
                            if (geometry->rayPick(relativePickOrigin, relativePickDirection, t, &distance))
                            {
                                if (distance < closest)
                                {
                                    closest = distance;
                                    closestResult.setHit(entity, distance, pickOrigin + pickDirection * distance);
                                }
                            }
                        }
                    }
                }

                // Visualizers may act as 'pick proxies'
                if (entity->hasVisualizers())
                {
                    Vector3d relativePickOrigin = pickOrigin - position;

                    // Calculate the distance to the plane containing the center of the visualizer
                    // and perpendicular to the pick direction.
                    double distanceToPlane = -pickDirection.dot(relativePickOrigin);

                    if (distanceToPlane > 0.0 && distanceToPlane < closest)
                    {
                        for (Entity::VisualizerTable::const_iterator iter = entity->visualizers()->begin();
                             iter != entity->visualizers()->end(); ++iter)
                        {
                            const Visualizer* visualizer = iter->second.ptr();
                            if (visualizer->isVisible() &&
                                visualizer->rayPick(relativePickOrigin, pickDirection, pixelAngle))
                            {
                                closest = distanceToPlane;
                                closestResult.setHit(entity, distanceToPlane, pickOrigin + pickDirection * distanceToPlane);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    if (closest < numeric_limits<double>::infinity())
    {
        if (result)
        {
            *result = closestResult;
        }
        return true;
    }
    else
    {
        return false;
    }
}