123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- import BoundingRectangle from "../Core/BoundingRectangle.js";
- import Color from "../Core/Color.js";
- import defaultValue from "../Core/defaultValue.js";
- import defined from "../Core/defined.js";
- import destroyObject from "../Core/destroyObject.js";
- import Framebuffer from "../Renderer/Framebuffer.js";
- import PassState from "../Renderer/PassState.js";
- import Renderbuffer from "../Renderer/Renderbuffer.js";
- import RenderbufferFormat from "../Renderer/RenderbufferFormat.js";
- import Texture from "../Renderer/Texture.js";
- /**
- * @private
- */
- function PickFramebuffer(context) {
- // Override per-command states
- var passState = new PassState(context);
- passState.blendingEnabled = false;
- passState.scissorTest = {
- enabled: true,
- rectangle: new BoundingRectangle(),
- };
- passState.viewport = new BoundingRectangle();
- this._context = context;
- this._fb = undefined;
- this._passState = passState;
- this._width = 0;
- this._height = 0;
- }
- PickFramebuffer.prototype.begin = function (screenSpaceRectangle, viewport) {
- var context = this._context;
- var width = viewport.width;
- var height = viewport.height;
- BoundingRectangle.clone(
- screenSpaceRectangle,
- this._passState.scissorTest.rectangle
- );
- // Initially create or recreate renderbuffers and framebuffer used for picking
- if (!defined(this._fb) || this._width !== width || this._height !== height) {
- this._width = width;
- this._height = height;
- this._fb = this._fb && this._fb.destroy();
- this._fb = new Framebuffer({
- context: context,
- colorTextures: [
- new Texture({
- context: context,
- width: width,
- height: height,
- }),
- ],
- depthStencilRenderbuffer: new Renderbuffer({
- context: context,
- width: width,
- height: height,
- format: RenderbufferFormat.DEPTH_STENCIL,
- }),
- });
- this._passState.framebuffer = this._fb;
- }
- this._passState.viewport.width = width;
- this._passState.viewport.height = height;
- return this._passState;
- };
- var colorScratch = new Color();
- PickFramebuffer.prototype.end = function (screenSpaceRectangle) {
- var width = defaultValue(screenSpaceRectangle.width, 1.0);
- var height = defaultValue(screenSpaceRectangle.height, 1.0);
- var context = this._context;
- var pixels = context.readPixels({
- x: screenSpaceRectangle.x,
- y: screenSpaceRectangle.y,
- width: width,
- height: height,
- framebuffer: this._fb,
- });
- var max = Math.max(width, height);
- var length = max * max;
- var halfWidth = Math.floor(width * 0.5);
- var halfHeight = Math.floor(height * 0.5);
- var x = 0;
- var y = 0;
- var dx = 0;
- var dy = -1;
- // Spiral around the center pixel, this is a workaround until
- // we can access the depth buffer on all browsers.
- // The region does not have to square and the dimensions do not have to be odd, but
- // loop iterations would be wasted. Prefer square regions where the size is odd.
- for (var i = 0; i < length; ++i) {
- if (
- -halfWidth <= x &&
- x <= halfWidth &&
- -halfHeight <= y &&
- y <= halfHeight
- ) {
- var index = 4 * ((halfHeight - y) * width + x + halfWidth);
- colorScratch.red = Color.byteToFloat(pixels[index]);
- colorScratch.green = Color.byteToFloat(pixels[index + 1]);
- colorScratch.blue = Color.byteToFloat(pixels[index + 2]);
- colorScratch.alpha = Color.byteToFloat(pixels[index + 3]);
- var object = context.getObjectByPickColor(colorScratch);
- if (defined(object)) {
- return object;
- }
- }
- // if (top right || bottom left corners) || (top left corner) || (bottom right corner + (1, 0))
- // change spiral direction
- if (x === y || (x < 0 && -x === y) || (x > 0 && x === 1 - y)) {
- var temp = dx;
- dx = -dy;
- dy = temp;
- }
- x += dx;
- y += dy;
- }
- return undefined;
- };
- PickFramebuffer.prototype.isDestroyed = function () {
- return false;
- };
- PickFramebuffer.prototype.destroy = function () {
- this._fb = this._fb && this._fb.destroy();
- return destroyObject(this);
- };
- export default PickFramebuffer;
|