Skip to content

Commit

Permalink
[Fix] Fix the bounding sphere calculation for spot lights (#4800)
Browse files Browse the repository at this point in the history
* [Fix] Fix the bounding sphere calculation for spot lights

* lint

* small improvement

Co-authored-by: Martin Valigursky <mvaligursky@snapchat.com>
  • Loading branch information
mvaligursky and Martin Valigursky committed Nov 1, 2022
1 parent d782385 commit 65d7b21
Showing 1 changed file with 22 additions and 18 deletions.
40 changes: 22 additions & 18 deletions src/scene/light.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import {
} from './constants.js';
import { ShadowRenderer } from './renderer/shadow-renderer.js';

const spotCenter = new Vec3();
const spotEndPoint = new Vec3();
const tmpVec = new Vec3();
const tmpBiases = {
bias: 0,
Expand Down Expand Up @@ -158,7 +156,7 @@ class Light {
this._position = new Vec3(0, 0, 0);
this._direction = new Vec3(0, 0, 0);
this._innerConeAngleCos = Math.cos(this._innerConeAngle * Math.PI / 180);
this._outerConeAngleCos = Math.cos(this._outerConeAngle * Math.PI / 180);
this._updateOuterAngle(this._outerConeAngle);

this._usePhysicalUnits = undefined;

Expand Down Expand Up @@ -416,7 +414,8 @@ class Light {
return;

this._outerConeAngle = value;
this._outerConeAngleCos = Math.cos(value * Math.PI / 180);
this._updateOuterAngle(value);

if (this._usePhysicalUnits) {
this._updateFinalColor();
}
Expand All @@ -426,6 +425,12 @@ class Light {
return this._outerConeAngle;
}

_updateOuterAngle(angle) {
const radAngle = angle * Math.PI / 180;
this._outerConeAngleCos = Math.cos(radAngle);
this._outerConeAngleSin = Math.sin(radAngle);
}

set intensity(value) {
if (this._intensity !== value) {
this._intensity = value;
Expand Down Expand Up @@ -713,24 +718,23 @@ class Light {

getBoundingSphere(sphere) {
if (this._type === LIGHTTYPE_SPOT) {
const range = this.attenuationEnd;

// based on https://bartwronski.com/2017/04/13/cull-that-cone/
const size = this.attenuationEnd;
const angle = this._outerConeAngle;
const f = Math.cos(angle * math.DEG_TO_RAD);
const cosAngle = this._outerConeAngleCos;
const node = this._node;
tmpVec.copy(node.up);

spotCenter.copy(node.up);
spotCenter.mulScalar(-range * 0.5 * f);
spotCenter.add(node.getPosition());
sphere.center = spotCenter;

spotEndPoint.copy(node.up);
spotEndPoint.mulScalar(-range);

tmpVec.copy(node.right);
tmpVec.mulScalar(Math.sin(angle * math.DEG_TO_RAD) * range);
spotEndPoint.add(tmpVec);
if (angle > 45) {
sphere.radius = size * this._outerConeAngleSin;
tmpVec.mulScalar(-size * cosAngle);
} else {
sphere.radius = size / (2 * cosAngle);
tmpVec.mulScalar(-sphere.radius);
}

sphere.radius = spotEndPoint.length() * 0.5;
sphere.center.add2(node.getPosition(), tmpVec);

} else if (this._type === LIGHTTYPE_OMNI) {
sphere.center = this._node.getPosition();
Expand Down

0 comments on commit 65d7b21

Please sign in to comment.