* Return the picked object(s) rendered within a given rectangle. * * @private * @param {object} context The active context. * @param {Uint8Array|Uint16Array|Float32Array|Uint32Array} pixels The pixels in the specified rectangle. * @param {number} width The rectangle width. * @param {number} he
(context, pixels, width, height, limit = 1)
| 43 | * @returns {object[]} A list of rendered objects, ordered by distance to the middle of the rectangle. |
| 44 | */ |
| 45 | function pickObjectsFromPixels(context, pixels, width, height, limit = 1) { |
| 46 | const max = Math.max(width, height); |
| 47 | const length = max * max; |
| 48 | const halfWidth = Math.floor(width * 0.5); |
| 49 | const halfHeight = Math.floor(height * 0.5); |
| 50 | |
| 51 | let x = 0; |
| 52 | let y = 0; |
| 53 | let dx = 0; |
| 54 | let dy = -1; |
| 55 | |
| 56 | // Spiral around the center pixel, this is a workaround until |
| 57 | // we can access the depth buffer on all browsers. |
| 58 | |
| 59 | // The region does not have to square and the dimensions do not have to be odd, but |
| 60 | // loop iterations would be wasted. Prefer square regions where the size is odd. |
| 61 | const objects = new Set(); |
| 62 | for (let i = 0; i < length; ++i) { |
| 63 | if ( |
| 64 | -halfWidth <= x && |
| 65 | x <= halfWidth && |
| 66 | -halfHeight <= y && |
| 67 | y <= halfHeight |
| 68 | ) { |
| 69 | const index = 4 * ((halfHeight - y) * width + x + halfWidth); |
| 70 | |
| 71 | const pickColor = Color.bytesToRgba( |
| 72 | pixels[index], |
| 73 | pixels[index + 1], |
| 74 | pixels[index + 2], |
| 75 | pixels[index + 3], |
| 76 | ); |
| 77 | |
| 78 | const object = context.getObjectByPickColor(pickColor); |
| 79 | if (defined(object)) { |
| 80 | objects.add(object); |
| 81 | if (objects.size >= limit) { |
| 82 | break; |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | // if (top right || bottom left corners) || (top left corner) || (bottom right corner + (1, 0)) |
| 88 | // change spiral direction |
| 89 | if (x === y || (x < 0 && -x === y) || (x > 0 && x === 1 - y)) { |
| 90 | const temp = dx; |
| 91 | dx = -dy; |
| 92 | dy = temp; |
| 93 | } |
| 94 | |
| 95 | x += dx; |
| 96 | y += dy; |
| 97 | } |
| 98 | return [...objects]; |
| 99 | } |
| 100 | |
| 101 | PickFramebuffer.prototype.begin = function (screenSpaceRectangle, viewport) { |
| 102 | const context = this._context; |
no test coverage detected
searching dependent graphs…