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()); }