Esempio n. 1
0
void Light::SetIntensitySortValue(const BoundingBox& box)
{
    // When sorting lights for object's maximum light cap, give priority based on attenuation and intensity
    switch (lightType_)
    {
    case LIGHT_DIRECTIONAL:
        sortValue_ = 1.0f / GetIntensityDivisor();
        break;

    case LIGHT_SPOT:
        {
            Vector3 centerPos = box.Center();
            Vector3 lightPos = node_->GetWorldPosition();
            Vector3 lightDir = node_->GetWorldDirection();
            Ray lightRay(lightPos, lightDir);

            Vector3 centerProj = lightRay.Project(centerPos);
            float centerDistance = (centerProj - lightPos).Length();
            Ray centerRay(centerProj, centerPos - centerProj);
            float centerAngle = centerRay.HitDistance(box) / centerDistance;

            // Check if a corner of the bounding box is closer to the light ray than the center, use its angle in that case
            Vector3 cornerPos = centerPos + box.HalfSize() * Vector3(centerPos.x_ < centerProj.x_ ? 1.0f : -1.0f,
                centerPos.y_ < centerProj.y_ ? 1.0f : -1.0f, centerPos.z_ < centerProj.z_ ? 1.0f : -1.0f);
            Vector3 cornerProj = lightRay.Project(cornerPos);
            float cornerDistance = (cornerProj - lightPos).Length();
            float cornerAngle = (cornerPos - cornerProj).Length() / cornerDistance;

            float spotAngle = Min(centerAngle, cornerAngle);
            float maxAngle = tanf(fov_ * M_DEGTORAD * 0.5f);
            float spotFactor = Min(spotAngle / maxAngle, 1.0f);
            // We do not know the actual range attenuation ramp, so take only spot attenuation into account
            float att = Max(1.0f - spotFactor * spotFactor, M_EPSILON);
            sortValue_ = 1.0f / GetIntensityDivisor(att);
        }
        break;

    case LIGHT_POINT:
        {
            Vector3 centerPos = box.Center();
            Vector3 lightPos = node_->GetWorldPosition();
            Vector3 lightDir = (centerPos - lightPos).Normalized();
            Ray lightRay(lightPos, lightDir);
            float distance = lightRay.HitDistance(box);
            float normDistance = distance / range_;
            float att = Max(1.0f - normDistance * normDistance, M_EPSILON);
            sortValue_ = 1.0f / (Max(color_.SumRGB(), 0.0f) * att + M_EPSILON);
        }
        break;
    }
}
void PhysicsWorld::GetRigidBodies(PODVector<RigidBody*>& result, const BoundingBox& box, unsigned collisionMask)
{
    ATOMIC_PROFILE(PhysicsBoxQuery);

    result.Clear();

    btBoxShape boxShape(ToBtVector3(box.HalfSize()));
    UniquePtr<btRigidBody> tempRigidBody(new btRigidBody(1.0f, 0, &boxShape));
    tempRigidBody->setWorldTransform(btTransform(btQuaternion::getIdentity(), ToBtVector3(box.Center())));
    tempRigidBody->activate();
    world_->addRigidBody(tempRigidBody.Get());

    PhysicsQueryCallback callback(result, collisionMask);
    world_->contactTest(tempRigidBody.Get(), callback);

    world_->removeRigidBody(tempRigidBody.Get());
}