Skip to content

Commit

Permalink
Cache and update Occluder instance in CentralBody.
Browse files Browse the repository at this point in the history
Instead of constructing a new instance every update, just set the camera position, since
that's the only thing that changes.
  • Loading branch information
shunter committed Jun 7, 2012
1 parent 87b9792 commit 7093060
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 39 deletions.
66 changes: 41 additions & 25 deletions Source/Core/Occluder.js
Expand Up @@ -13,7 +13,7 @@ define([

/**
* Creates an Occluder derived from an object's position and radius, as well as the camera position.
* The occluder can be used to determine wether or not other objects are visible or hidden behind the
* The occluder can be used to determine whether or not other objects are visible or hidden behind the
* visible horizon defined by the occluder and camera position.
*
* @name Occluder
Expand All @@ -36,36 +36,21 @@ define([
if (!occluderBS) {
throw new DeveloperError("occluder bounding sphere is required.", "occluderPBS");
}

if (!cameraPosition) {
throw new DeveloperError("camera position is required.", "cameraPosition");
}

var cameraPos = Cartesian3.clone(cameraPosition);
var occluderPosition = occluderBS.center.clone();
var occluderRadius = occluderBS.radius;
this._occluderPosition = occluderBS.center.clone();
this._occluderRadius = occluderBS.radius;

var cameraToOccluderVec = occluderPosition.subtract(cameraPosition);
var invCameraToOccluderDistance = cameraToOccluderVec.magnitudeSquared();
var occluderRadiusSqrd = occluderRadius * occluderRadius;
var horizonDistance;
var horizonPlaneNormal;
var horizonPlanePosition;
if (invCameraToOccluderDistance > occluderRadiusSqrd) {
horizonDistance = Math.sqrt(invCameraToOccluderDistance - occluderRadiusSqrd);
invCameraToOccluderDistance = 1.0 / Math.sqrt(invCameraToOccluderDistance);
horizonPlaneNormal = cameraToOccluderVec.multiplyWithScalar(invCameraToOccluderDistance);
var nearPlaneDistance = horizonDistance * horizonDistance * invCameraToOccluderDistance;
horizonPlanePosition = cameraPos.add(horizonPlaneNormal.multiplyWithScalar(nearPlaneDistance));
} else {
horizonDistance = Number.MAX_VALUE;
}
this._horizonDistance = 0.0;
this._horizonPlaneNormal = undefined;
this._horizonPlanePosition = undefined;
this._cameraPosition = undefined;

this._occluderPosition = occluderPosition;
this._occluderRadius = occluderRadius;
this._cameraPosition = cameraPos.clone();
this._horizonDistance = horizonDistance;
this._horizonPlaneNormal = horizonPlaneNormal;
this._horizonPlanePosition = horizonPlanePosition;
// setCameraPosition fills in the above values
this.setCameraPosition(cameraPosition);
}

/**
Expand All @@ -88,6 +73,37 @@ define([
return this._occluderRadius;
};

/**
* Sets the position of the camera.
*
* @param {Cartesian3} cameraPosition The new position of the camera.
*/
Occluder.prototype.setCameraPosition = function(cameraPosition) {
cameraPosition = Cartesian3.clone(cameraPosition);

var cameraToOccluderVec = this._occluderPosition.subtract(cameraPosition);
var invCameraToOccluderDistance = cameraToOccluderVec.magnitudeSquared();
var occluderRadiusSqrd = this._occluderRadius * this._occluderRadius;

var horizonDistance;
var horizonPlaneNormal;
var horizonPlanePosition;
if (invCameraToOccluderDistance > occluderRadiusSqrd) {
horizonDistance = Math.sqrt(invCameraToOccluderDistance - occluderRadiusSqrd);
invCameraToOccluderDistance = 1.0 / Math.sqrt(invCameraToOccluderDistance);
horizonPlaneNormal = cameraToOccluderVec.multiplyWithScalar(invCameraToOccluderDistance);
var nearPlaneDistance = horizonDistance * horizonDistance * invCameraToOccluderDistance;
horizonPlanePosition = cameraPosition.add(horizonPlaneNormal.multiplyWithScalar(nearPlaneDistance));
} else {
horizonDistance = Number.MAX_VALUE;
}

this._horizonDistance = horizonDistance;
this._horizonPlaneNormal = horizonPlaneNormal;
this._horizonPlanePosition = horizonPlanePosition;
this._cameraPosition = cameraPosition;
};

/**
* Determines whether or not an object, the <code>occludee</code>, is hidden from view by the occluder.
*
Expand Down
31 changes: 17 additions & 14 deletions Source/Scene/CentralBody.js
Expand Up @@ -200,6 +200,7 @@ define([
zoom : 0,
ellipsoid : ellipsoid
});
this._occluder = new Occluder(new BoundingSphere(Cartesian3.ZERO, ellipsoid.getMinimumRadius()), Cartesian3.ZERO);

this._renderQueue = new Queue();
this._imageQueue = new Queue();
Expand Down Expand Up @@ -834,7 +835,7 @@ define([
}
};

CentralBody.prototype._cull = function(tile, occluder, sceneState) {
CentralBody.prototype._cull = function(tile, sceneState) {
if (sceneState.mode === SceneMode.SCENE2D) {
var bRect = tile.get2DBoundingRectangle(sceneState.scene2D.projection);

Expand All @@ -856,17 +857,18 @@ define([

if (sceneState.mode === SceneMode.SCENE3D) {
var occludeePoint = tile.getOccludeePoint();
var occluder = this._occluder;
return (occludeePoint && !occluder.isVisible(new BoundingSphere(occludeePoint, 0.0))) || !occluder.isVisible(boundingVolume);
}

return false;
};

CentralBody.prototype._throttleImages = function(occluder, sceneState) {
CentralBody.prototype._throttleImages = function(sceneState) {
for ( var i = 0, len = this._imageQueue.length; i < len && i < this._imageThrottleLimit; ++i) {
var tile = this._imageQueue.dequeue();

if (this._cull(tile, occluder, sceneState)) {
if (this._cull(tile, sceneState)) {
tile.state = TileState.READY;
continue;
}
Expand Down Expand Up @@ -894,11 +896,11 @@ define([
return canvas;
};

CentralBody.prototype._throttleReprojection = function(occluder, sceneState) {
CentralBody.prototype._throttleReprojection = function(sceneState) {
for ( var i = 0, len = this._reprojectQueue.length; i < len && i < this._reprojectThrottleLimit; ++i) {
var tile = this._reprojectQueue.dequeue();

if (this._cull(tile, occluder, sceneState)) {
if (this._cull(tile, sceneState)) {
tile.image = undefined;
tile.state = TileState.READY;
continue;
Expand All @@ -910,11 +912,11 @@ define([
}
};

CentralBody.prototype._throttleTextures = function(context, occluder, sceneState) {
CentralBody.prototype._throttleTextures = function(context, sceneState) {
for ( var i = 0, len = this._textureQueue.length; i < len && i < this._textureThrottleLimit; ++i) {
var tile = this._textureQueue.dequeue();

if (this._cull(tile, occluder, sceneState) || !tile.image) {
if (this._cull(tile, sceneState) || !tile.image) {
tile.image = undefined;
tile.state = TileState.READY;
continue;
Expand Down Expand Up @@ -1326,7 +1328,7 @@ define([
halfHeight * 2.0);
};

CentralBody.prototype._fillPoles = function(context, occluder, sceneState) {
CentralBody.prototype._fillPoles = function(context, sceneState) {
if (typeof this._dayTileProvider === 'undefined' || sceneState.mode !== SceneMode.SCENE3D) {
return;
}
Expand All @@ -1344,6 +1346,7 @@ define([
var mesh;
var rect;
var positions;
var occluder = this._occluder;

// handle north pole
if (this._dayTileProvider.maxExtent.north < CesiumMath.PI_OVER_TWO) {
Expand Down Expand Up @@ -1908,20 +1911,20 @@ define([
this._spSky = this._spSkyFromAtmosphere;
}

var occluder = new Occluder(new BoundingSphere(Cartesian3.ZERO, this._ellipsoid.getMinimumRadius()), cameraPosition);
this._occluder.setCameraPosition(cameraPosition);

// TODO: refactor
this._fillPoles(context, occluder, sceneState);
this._fillPoles(context, sceneState);

this._throttleImages(occluder, sceneState);
this._throttleReprojection(occluder, sceneState);
this._throttleTextures(context, occluder, sceneState);
this._throttleImages(sceneState);
this._throttleReprojection(sceneState);
this._throttleTextures(context, sceneState);

var stack = [this._rootTile];
while (stack.length !== 0) {
var tile = stack.pop();

if (this._cull(tile, occluder, sceneState)) {
if (this._cull(tile, sceneState)) {
continue;
}

Expand Down

1 comment on commit 7093060

@pjcozzi
Copy link
Contributor

@pjcozzi pjcozzi commented on 7093060 Jun 7, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bagnell this is all you...

Please sign in to comment.