123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- 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;
|