entity/ray/RayHandler.tstypescript
import * as shaders from "../../shaders/ray/ray";
import { concatArrays, concatTypedArrays, makeArrayTyped, spliceArray, spliceTypedArray } from "../../utils/shared";
import type { TypedArray } from "../../utils/shared";
import { EntityCollection } from "../EntityCollection";
import { Ray } from "./Ray";
import { Renderer } from "../../renderer/Renderer";
import { Vec3 } from "../../math/Vec3";
import { Vec4 } from "../../math/Vec4";
import type { WebGLBufferExt } from "../../webgl/Handler";
import type { ShaderProgram } from "../../webgl/ShaderProgram";
import { srgbToLinear } from "../../utils/colorSpace";
const PICKINGCOLOR_BUFFER = 0;
const START_POSITION_BUFFER = 1;
const END_POSITION_BUFFER = 2;
const RGBA_BUFFER = 3;
const THICKNESS_BUFFER = 4;
const VERTEX_BUFFER = 5;
const TEXCOORD_BUFFER = 6;
const TEXOFFSET_BUFFER = 7;
const STROKESIZE_BUFFER = 8;
const RAY_VERTICES_COUNT = 6;
/*
* og.RayHandler
*
*
*/
class RayHandler {
static __counter__: number = 0;
protected __id: number;
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
public pickingEnabled: boolean;
public _entityCollection: EntityCollection;
protected _renderer: Renderer | null;
protected _rays: Ray[];
protected _opaqueCounterIndex: number;
protected _vertexBuffer: WebGLBufferExt | null;
protected _startPositionHighBuffer: WebGLBufferExt | null;
protected _startPositionLowBuffer: WebGLBufferExt | null;
protected _endPositionHighBuffer: WebGLBufferExt | null;
protected _endPositionLowBuffer: WebGLBufferExt | null;
protected _thicknessBuffer: WebGLBufferExt | null;
protected _rgbaBuffer: WebGLBufferExt | null;
protected _pickingColorBuffer: WebGLBufferExt | null;
protected _texCoordBuffer: WebGLBufferExt | null;
protected _texOffsetBuffer: WebGLBufferExt | null;
protected _strokeSizeBuffer: WebGLBufferExt | null;
protected _vertexArr: TypedArray | number[];
protected _startPositionHighArr: TypedArray | number[];
protected _startPositionLowArr: TypedArray | number[];
protected _endPositionHighArr: TypedArray | number[];
protected _endPositionLowArr: TypedArray | number[];
protected _thicknessArr: TypedArray | number[];
protected _rgbaArr: TypedArray | number[];
protected _pickingColorArr: TypedArray | number[];
protected _texCoordArr: TypedArray;
protected _texOffsetArr: TypedArray;
protected _strokeSizeArr: TypedArray;
protected _buffersUpdateCallbacks: Function[];
protected _changedBuffers: boolean[];
constructor(entityCollection: EntityCollection) {
this.__id = RayHandler.__counter__++;
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
this._entityCollection = entityCollection;
this._renderer = null;
this._rays = [];
this._opaqueCounterIndex = 0;
this._vertexBuffer = null;
this._startPositionHighBuffer = null;
this._startPositionLowBuffer = null;
this._endPositionHighBuffer = null;
this._endPositionLowBuffer = null;
this._thicknessBuffer = null;
this._rgbaBuffer = null;
this._pickingColorBuffer = null;
this._texCoordBuffer = null;
this._texOffsetBuffer = null;
this._strokeSizeBuffer = null;
this._vertexArr = [];
this._startPositionHighArr = [];
this._startPositionLowArr = [];
this._endPositionHighArr = [];
this._endPositionLowArr = [];
this._thicknessArr = [];
this._rgbaArr = [];
this._pickingColorArr = [];
this._texCoordArr = new Float32Array([]);
this._texOffsetArr = new Float32Array([]);
this._strokeSizeArr = new Float32Array([]);
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[VERTEX_BUFFER] = this.createVertexBuffer;
this._buffersUpdateCallbacks[START_POSITION_BUFFER] = this.createStartPositionBuffer;
this._buffersUpdateCallbacks[END_POSITION_BUFFER] = this.createEndPositionBuffer;
this._buffersUpdateCallbacks[THICKNESS_BUFFER] = this.createThicknessBuffer;
this._buffersUpdateCallbacks[RGBA_BUFFER] = this.createRgbaBuffer;
this._buffersUpdateCallbacks[PICKINGCOLOR_BUFFER] = this.createPickingColorBuffer;
this._buffersUpdateCallbacks[TEXCOORD_BUFFER] = this.createTexCoordBuffer;
this._buffersUpdateCallbacks[TEXOFFSET_BUFFER] = this.createTexOffsetBuffer;
this._buffersUpdateCallbacks[STROKESIZE_BUFFER] = this.createStrokeSizeBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
}
static concArr(dest: number[], curr: number[]) {
for (let i = 0; i < curr.length; i++) {
dest.push(curr[i]);
}
}
protected _isRayOpaque(ray: Ray): boolean {
const opacity = ray.getOpacity();
return ray._startColor.w * opacity >= 1.0 || ray._endColor.w * opacity >= 1.0;
}
protected _swapArrayItems(arr: number[] | TypedArray, itemSize: number, firstIndex: number, secondIndex: number) {
if (firstIndex === secondIndex) {
return;
}
const firstOffset = firstIndex * itemSize;
const secondOffset = secondIndex * itemSize;
for (let i = 0; i < itemSize; i++) {
const tmp = arr[firstOffset + i];
arr[firstOffset + i] = arr[secondOffset + i];
arr[secondOffset + i] = tmp;
}
}
protected _swapRayData(firstIndex: number, secondIndex: number) {
if (firstIndex === secondIndex) {
return;
}
this._swapArrayItems(this._vertexArr, 12, firstIndex, secondIndex);
this._swapArrayItems(this._startPositionHighArr, 18, firstIndex, secondIndex);
this._swapArrayItems(this._startPositionLowArr, 18, firstIndex, secondIndex);
this._swapArrayItems(this._endPositionHighArr, 18, firstIndex, secondIndex);
this._swapArrayItems(this._endPositionLowArr, 18, firstIndex, secondIndex);
this._swapArrayItems(this._thicknessArr, 6, firstIndex, secondIndex);
this._swapArrayItems(this._rgbaArr, 24, firstIndex, secondIndex);
this._swapArrayItems(this._pickingColorArr, 18, firstIndex, secondIndex);
this._swapArrayItems(this._texCoordArr, 24, firstIndex, secondIndex);
this._swapArrayItems(this._texOffsetArr, 6, firstIndex, secondIndex);
this._swapArrayItems(this._strokeSizeArr, 6, firstIndex, secondIndex);
const firstRay = this._rays[firstIndex];
const secondRay = this._rays[secondIndex];
this._rays[firstIndex] = secondRay;
this._rays[secondIndex] = firstRay;
firstRay._handlerIndex = secondIndex;
secondRay._handlerIndex = firstIndex;
}
protected _insertRayByOpacity(rayIndex: number, isOpaque: boolean) {
if (!isOpaque) {
return;
}
const targetIndex = this._opaqueCounterIndex;
this._swapRayData(rayIndex, targetIndex);
this._opaqueCounterIndex++;
}
protected _updateRayOpacityState(rayIndex: number, isOpaque: boolean): boolean {
const wasOpaque = rayIndex < this._opaqueCounterIndex;
if (wasOpaque === isOpaque) {
return false;
}
if (isOpaque) {
const targetIndex = this._opaqueCounterIndex;
this._swapRayData(rayIndex, targetIndex);
this._opaqueCounterIndex++;
} else {
this._opaqueCounterIndex--;
const targetIndex = this._opaqueCounterIndex;
this._swapRayData(rayIndex, targetIndex);
}
return true;
}
public reloadTextures() {
for (let i = 0; i < this._rays.length; i++) {
let ri = this._rays[i];
ri.reloadTexture();
}
}
public get rays(): Ray[] {
return [...this._rays];
}
public initProgram() {
if (this._renderer) {
this._renderer.addShaders(shaders.rayScreen());
if (!this._renderer.deferredDisabled) {
this._renderer.addShaders(shaders.rayScreenWoit());
}
// @todo: ray picking
// if (!this._renderer.handler.programs.billboardPicking) {
// this._renderer.handler.addProgram(shaders.billboardPicking());
// }
}
}
public setRenderer(renderer: Renderer) {
this._renderer = renderer;
this.initProgram();
}
public refresh() {
let i = this._changedBuffers.length;
while (i--) {
this._setChangedBuffer(i);
}
}
protected _setChangedBuffer(index: number) {
this._changedBuffers[index] = true;
this._renderer && this._renderer.requestRedraw();
}
protected _removeRays() {
let i = this._rays.length;
while (i--) {
let ri = this._rays[i];
ri._handlerIndex = -1;
ri._handler = null;
}
this._rays.length = 0;
this._rays = [];
this._opaqueCounterIndex = 0;
}
public clear() {
//@ts-ignore
this._vertexArr = null;
//@ts-ignore
this._startPositionHighArr = null;
//@ts-ignore
this._startPositionLowArr = null;
//@ts-ignore
this._endPositionHighArr = null;
//@ts-ignore
this._endPositionLowArr = null;
//@ts-ignore
this._thicknessArr = null;
//@ts-ignore
this._rgbaArr = null;
//@ts-ignore
this._texCoordArr = null;
//@ts-ignore
this._texOffsetArr = null;
//@ts-ignore
this._strokeSizeArr = null;
this._vertexArr = new Float32Array([]);
this._texCoordArr = new Float32Array([]);
this._startPositionHighArr = new Float32Array([]);
this._startPositionLowArr = new Float32Array([]);
this._endPositionHighArr = new Float32Array([]);
this._endPositionLowArr = new Float32Array([]);
this._thicknessArr = new Float32Array([]);
this._rgbaArr = new Float32Array([]);
this._texOffsetArr = new Float32Array([]);
this._strokeSizeArr = new Float32Array([]);
this._removeRays();
this._deleteBuffers();
this.refresh();
}
protected _deleteBuffers() {
if (this._renderer) {
let gl = this._renderer.handler.gl;
if (gl) {
gl.deleteBuffer(this._startPositionHighBuffer!);
gl.deleteBuffer(this._startPositionLowBuffer!);
gl.deleteBuffer(this._endPositionHighBuffer!);
gl.deleteBuffer(this._endPositionLowBuffer!);
gl.deleteBuffer(this._thicknessBuffer!);
gl.deleteBuffer(this._rgbaBuffer!);
gl.deleteBuffer(this._vertexBuffer!);
gl.deleteBuffer(this._texCoordBuffer!);
gl.deleteBuffer(this._texOffsetBuffer!);
gl.deleteBuffer(this._strokeSizeBuffer!);
}
this._startPositionHighBuffer = null;
this._startPositionLowBuffer = null;
this._endPositionHighBuffer = null;
this._endPositionLowBuffer = null;
this._thicknessBuffer = null;
this._rgbaBuffer = null;
this._vertexBuffer = null;
this._texCoordBuffer = null;
this._texOffsetBuffer = null;
this._strokeSizeBuffer = null;
}
}
public update() {
if (this._renderer) {
let i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
}
}
public add(ray: Ray) {
if (ray._handlerIndex == -1) {
ray._handler = this;
ray._handlerIndex = this._rays.length;
this._rays.push(ray);
this._addRayToArrays(ray);
this._insertRayByOpacity(ray._handlerIndex, this._isRayOpaque(ray));
this.refresh();
ray.reloadTexture();
}
}
protected _addRayToArrays(ray: Ray) {
if (ray.getVisibility()) {
this._vertexArr = concatArrays(
this._vertexArr,
[-0.5, 1.0, -0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 1.0, -0.5, 1.0]
);
} else {
this._vertexArr = concatArrays(
this._vertexArr,
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
);
}
let x = ray.texOffset;
this._texOffsetArr = concatTypedArrays(this._texOffsetArr, [x, x, x, x, x, x]);
x = ray.strokeSize;
this._strokeSizeArr = concatTypedArrays(this._strokeSizeArr, [x, x, x, x, x, x]);
this._texCoordArr = concatTypedArrays(
this._texCoordArr,
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
);
x = ray._startPositionHigh.x;
let y = ray._startPositionHigh.y,
z = ray._startPositionHigh.z;
this._startPositionHighArr = concatArrays(this._startPositionHighArr, [
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z
]);
x = ray._startPositionLow.x;
y = ray._startPositionLow.y;
z = ray._startPositionLow.z;
this._startPositionLowArr = concatArrays(this._startPositionLowArr, [
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z
]);
x = ray._endPositionHigh.x;
y = ray._endPositionHigh.y;
z = ray._endPositionHigh.z;
this._endPositionHighArr = concatArrays(this._endPositionHighArr, [
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z
]);
x = ray._endPositionLow.x;
y = ray._endPositionLow.y;
z = ray._endPositionLow.z;
this._endPositionLowArr = concatArrays(this._endPositionLowArr, [
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z
]);
x = ray._thickness;
this._thicknessArr = concatArrays(this._thicknessArr, [x, x, x, x, x, x]);
const opacity = ray.getOpacity();
let r0 = srgbToLinear(ray._startColor.x),
g0 = srgbToLinear(ray._startColor.y),
b0 = srgbToLinear(ray._startColor.z),
a0 = ray._startColor.w * opacity,
r1 = srgbToLinear(ray._endColor.x),
g1 = srgbToLinear(ray._endColor.y),
b1 = srgbToLinear(ray._endColor.z),
a1 = ray._endColor.w * opacity;
this._rgbaArr = concatArrays(this._rgbaArr, [
r1,
g1,
b1,
a1,
r0,
g0,
b0,
a0,
r0,
g0,
b0,
a0,
r0,
g0,
b0,
a0,
r1,
g1,
b1,
a1,
r1,
g1,
b1,
a1
]);
x = ray._entity!._pickingColor.x / 255;
y = ray._entity!._pickingColor.y / 255;
z = ray._entity!._pickingColor.z / 255;
this._pickingColorArr = concatArrays(this._pickingColorArr, [
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z,
x,
y,
z
]);
}
protected _displayPASS(startRayIndex: number, endRayIndex: number, rayProgram: ShaderProgram) {
let r = this._renderer!;
let h = r.handler;
rayProgram.activate();
let sh = rayProgram;
let sha = sh.attributes,
shu = sh.uniforms;
let gl = h.gl!,
ec = this._entityCollection;
if (rayProgram === r.handler.programs.rayScreenWoit) {
gl.uniform1f(shu.useReverseDepth, r.activeCamera.reverseDepthActive ? 1.0 : 0.0);
}
gl.disable(gl.CULL_FACE);
gl.uniform1f(shu.uOpacity, ec._fadingOpacity);
gl.uniform1i(shu.u_texAtlas, 0);
gl.uniformMatrix4fv(shu.viewMatrix, false, r.activeCamera!.getViewMatrix());
gl.uniformMatrix4fv(shu.projectionMatrix, false, r.activeCamera!.getProjectionMatrix());
gl.uniform3fv(shu.eyePositionHigh, r.activeCamera!.eyeHigh);
gl.uniform3fv(shu.eyePositionLow, r.activeCamera!.eyeLow);
gl.uniform1f(shu.resolution, r.activeCamera!._tanViewAngle_hradOneByHeight);
gl.uniform2fv(shu.viewport, [r.handler.canvas!.width, r.handler.canvas!.height]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._startPositionHighBuffer!);
gl.vertexAttribPointer(sha.a_startPosHigh, this._startPositionHighBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._startPositionLowBuffer!);
gl.vertexAttribPointer(sha.a_startPosLow, this._startPositionLowBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._endPositionHighBuffer!);
gl.vertexAttribPointer(sha.a_endPosHigh, this._endPositionHighBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._endPositionLowBuffer!);
gl.vertexAttribPointer(sha.a_endPosLow, this._endPositionLowBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rgbaBuffer!);
gl.vertexAttribPointer(sha.a_rgba, this._rgbaBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._thicknessBuffer!);
gl.vertexAttribPointer(sha.a_thickness, this._thicknessBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer!);
gl.vertexAttribPointer(sha.a_vertices, this._vertexBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer!);
gl.vertexAttribPointer(sha.a_texCoord, this._texCoordBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texOffsetBuffer!);
gl.vertexAttribPointer(sha.a_texOffset, this._texOffsetBuffer!.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._strokeSizeBuffer!);
gl.vertexAttribPointer(sha.a_strokeSize, this._strokeSizeBuffer!.itemSize, gl.FLOAT, false, 0, 0);
const numRays = endRayIndex - startRayIndex;
if (numRays > 0) {
gl.drawArrays(gl.TRIANGLES, startRayIndex * RAY_VERTICES_COUNT, numRays * RAY_VERTICES_COUNT);
}
gl.enable(gl.CULL_FACE);
}
protected _pickingPASS() {
// ...
}
public drawForward() {
this.drawOpaque();
}
public drawOpaque() {
if (this._rays.length) {
this.update();
this._displayPASS(0, this._opaqueCounterIndex, this._renderer!.handler.programs.rayScreen);
}
}
public drawTransparent() {
if (this._opaqueCounterIndex < this._rays.length) {
this._displayPASS(
this._opaqueCounterIndex,
this._rays.length,
this._renderer!.handler.programs.rayScreenWoit
);
}
}
public drawTransparentForward() {
if (this._opaqueCounterIndex < this._rays.length) {
this._displayPASS(this._opaqueCounterIndex, this._rays.length, this._renderer!.handler.programs.rayScreen);
}
}
public drawPicking() {
if (this._rays.length && this.pickingEnabled) {
this._pickingPASS();
}
}
public reindexRaysArray(startIndex: number) {
let r = this._rays;
for (let i = startIndex; i < r.length; i++) {
r[i]._handlerIndex = i;
}
}
protected _removeRay(ray: Ray) {
let removeIndex = ray._handlerIndex;
if (removeIndex < this._opaqueCounterIndex) {
this._opaqueCounterIndex--;
this._swapRayData(removeIndex, this._opaqueCounterIndex);
removeIndex = this._opaqueCounterIndex;
}
const lastIndex = this._rays.length - 1;
this._swapRayData(removeIndex, lastIndex);
this._rays.pop();
let i = lastIndex * 24;
this._rgbaArr = spliceArray(this._rgbaArr, i, 24);
this._texCoordArr = spliceTypedArray(this._texCoordArr, i, 24);
i = lastIndex * 18;
this._startPositionHighArr = spliceArray(this._startPositionHighArr, i, 18);
this._startPositionLowArr = spliceArray(this._startPositionLowArr, i, 18);
this._endPositionHighArr = spliceArray(this._endPositionHighArr, i, 18);
this._endPositionLowArr = spliceArray(this._endPositionLowArr, i, 18);
this._pickingColorArr = spliceArray(this._pickingColorArr, i, 18);
i = lastIndex * 12;
this._vertexArr = spliceArray(this._vertexArr, i, 12);
i = lastIndex * 6;
this._thicknessArr = spliceArray(this._thicknessArr, i, 6);
this._texOffsetArr = spliceTypedArray(this._texOffsetArr, i, 6);
this._strokeSizeArr = spliceTypedArray(this._strokeSizeArr, i, 6);
this.refresh();
ray._handlerIndex = -1;
ray._handler = null;
}
public remove(ray: Ray) {
if (ray._handler && this.__id === ray._handler.__id) {
this._removeRay(ray);
}
}
public setStartPositionArr(index: number, positionHigh: Vec3, positionLow: Vec3) {
let i = index * 18;
// High
let a = this._startPositionHighArr,
x = positionHigh.x,
y = positionHigh.y,
z = positionHigh.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
// Low
a = this._startPositionLowArr;
x = positionLow.x;
y = positionLow.y;
z = positionLow.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._setChangedBuffer(START_POSITION_BUFFER);
}
public setEndPositionArr(index: number, positionHigh: Vec3, positionLow: Vec3) {
let i = index * 18;
// High
let a = this._endPositionHighArr,
x = positionHigh.x,
y = positionHigh.y,
z = positionHigh.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
// Low
a = this._endPositionLowArr;
x = positionLow.x;
y = positionLow.y;
z = positionLow.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._setChangedBuffer(END_POSITION_BUFFER);
}
public setPickingColorArr(index: number, color: Vec3) {
let i = index * 18;
let a = this._pickingColorArr,
x = color.x / 255,
y = color.y / 255,
z = color.z / 255;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._setChangedBuffer(PICKINGCOLOR_BUFFER);
}
public setRgbaArr(index: number, startColor: Vec4, endColor: Vec4) {
let i = index * 24;
let a = this._rgbaArr,
r0 = srgbToLinear(startColor.x),
g0 = srgbToLinear(startColor.y),
b0 = srgbToLinear(startColor.z),
a0 = startColor.w,
r1 = srgbToLinear(endColor.x),
g1 = srgbToLinear(endColor.y),
b1 = srgbToLinear(endColor.z),
a1 = endColor.w;
a[i] = r1;
a[i + 1] = g1;
a[i + 2] = b1;
a[i + 3] = a1;
a[i + 4] = r0;
a[i + 5] = g0;
a[i + 6] = b0;
a[i + 7] = a0;
a[i + 8] = r0;
a[i + 9] = g0;
a[i + 10] = b0;
a[i + 11] = a0;
a[i + 12] = r0;
a[i + 13] = g0;
a[i + 14] = b0;
a[i + 15] = a0;
a[i + 16] = r1;
a[i + 17] = g1;
a[i + 18] = b1;
a[i + 19] = a1;
a[i + 20] = r1;
a[i + 21] = g1;
a[i + 22] = b1;
a[i + 23] = a1;
const opacityChanged = this._updateRayOpacityState(index, a0 >= 1.0 || a1 >= 1.0);
if (opacityChanged) {
this.refresh();
} else {
this._setChangedBuffer(RGBA_BUFFER);
}
}
public setThicknessArr(index: number, thickness: number) {
let i = index * 6;
let a = this._thicknessArr;
a[i] = thickness;
a[i + 1] = thickness;
a[i + 2] = thickness;
a[i + 3] = thickness;
a[i + 4] = thickness;
a[i + 5] = thickness;
this._setChangedBuffer(THICKNESS_BUFFER);
}
public setVisibility(index: number, visibility: boolean) {
let vArr: number[];
if (visibility) {
vArr = [-0.5, 1.0, -0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 1.0, -0.5, 1.0];
} else {
vArr = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
}
this.setVertexArr(index, vArr);
}
public setVertexArr(index: number, vertexArr: number[]) {
let i = index * 12;
let a = this._vertexArr;
a[i] = vertexArr[0];
a[i + 1] = vertexArr[1];
a[i + 2] = vertexArr[2];
a[i + 3] = vertexArr[3];
a[i + 4] = vertexArr[4];
a[i + 5] = vertexArr[5];
a[i + 6] = vertexArr[6];
a[i + 7] = vertexArr[7];
a[i + 8] = vertexArr[8];
a[i + 9] = vertexArr[9];
a[i + 10] = vertexArr[10];
a[i + 11] = vertexArr[11];
this._setChangedBuffer(VERTEX_BUFFER);
}
public createStartPositionBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._startPositionHighBuffer as WebGLBuffer);
this._startPositionHighArr = makeArrayTyped(this._startPositionHighArr);
this._startPositionHighBuffer = h.createArrayBuffer(
this._startPositionHighArr as Float32Array,
3,
this._startPositionHighArr.length / 3,
h.gl!.DYNAMIC_DRAW
);
h.gl!.deleteBuffer(this._startPositionLowBuffer as WebGLBuffer);
this._startPositionLowArr = makeArrayTyped(this._startPositionLowArr);
this._startPositionLowBuffer = h.createArrayBuffer(
this._startPositionLowArr as Float32Array,
3,
this._startPositionLowArr.length / 3,
h.gl!.DYNAMIC_DRAW
);
}
public createEndPositionBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._endPositionHighBuffer as WebGLBuffer);
this._endPositionHighArr = makeArrayTyped(this._endPositionHighArr);
this._endPositionHighBuffer = h.createArrayBuffer(
this._endPositionHighArr as Float32Array,
3,
this._endPositionHighArr.length / 3,
h.gl!.DYNAMIC_DRAW
);
h.gl!.deleteBuffer(this._endPositionLowBuffer as WebGLBuffer);
this._endPositionLowArr = makeArrayTyped(this._endPositionLowArr);
this._endPositionLowBuffer = h.createArrayBuffer(
this._endPositionLowArr as Float32Array,
3,
this._endPositionLowArr.length / 3,
h.gl!.DYNAMIC_DRAW
);
}
public createRgbaBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._rgbaBuffer as WebGLBuffer);
this._rgbaArr = makeArrayTyped(this._rgbaArr);
this._rgbaBuffer = h.createArrayBuffer(this._rgbaArr as Float32Array, 4, this._rgbaArr.length / 4);
}
public createThicknessBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._thicknessBuffer as WebGLBuffer);
this._thicknessArr = makeArrayTyped(this._thicknessArr);
this._thicknessBuffer = h.createArrayBuffer(
this._thicknessArr as Float32Array,
1,
this._thicknessArr.length,
h.gl!.DYNAMIC_DRAW
);
}
public createVertexBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._vertexBuffer as WebGLBuffer);
this._vertexArr = makeArrayTyped(this._vertexArr);
this._vertexBuffer = h.createArrayBuffer(
this._vertexArr as Float32Array,
2,
this._vertexArr.length / 2,
h.gl!.DYNAMIC_DRAW
);
}
public createTexCoordBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._texCoordBuffer!);
this._texCoordBuffer = h.createArrayBuffer(this._texCoordArr, 4, this._texCoordArr.length / 4);
}
public createTexOffsetBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._texOffsetBuffer!);
this._texOffsetBuffer = h.createArrayBuffer(this._texOffsetArr, 1, this._texOffsetArr.length);
}
public createStrokeSizeBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._strokeSizeBuffer!);
this._strokeSizeBuffer = h.createArrayBuffer(this._strokeSizeArr, 1, this._strokeSizeArr.length);
}
public createPickingColorBuffer() {
let h = this._renderer!.handler;
h.gl!.deleteBuffer(this._pickingColorBuffer as WebGLBuffer);
this._pickingColorArr = makeArrayTyped(this._pickingColorArr);
this._pickingColorBuffer = h.createArrayBuffer(
this._pickingColorArr as Float32Array,
3,
this._pickingColorArr.length / 3
);
}
public setTexCoordArr(index: number, tcoordArr: number[] | TypedArray) {
let minY = tcoordArr[1],
imgHeight = tcoordArr[3] - minY;
let i = index * 24;
let a = this._texCoordArr;
a[i] = tcoordArr[0];
a[i + 1] = tcoordArr[1];
a[i + 2] = minY;
a[i + 3] = imgHeight;
a[i + 4] = tcoordArr[2];
a[i + 5] = tcoordArr[3];
a[i + 6] = minY;
a[i + 7] = imgHeight;
a[i + 8] = tcoordArr[4];
a[i + 9] = tcoordArr[5];
a[i + 10] = minY;
a[i + 11] = imgHeight;
a[i + 12] = tcoordArr[6];
a[i + 13] = tcoordArr[7];
a[i + 14] = minY;
a[i + 15] = imgHeight;
a[i + 16] = tcoordArr[8];
a[i + 17] = tcoordArr[9];
a[i + 18] = minY;
a[i + 19] = imgHeight;
a[i + 20] = tcoordArr[10];
a[i + 21] = tcoordArr[11];
a[i + 22] = minY;
a[i + 23] = imgHeight;
this._setChangedBuffer(TEXCOORD_BUFFER);
}
public setTextureDisabled(index: number) {
let i = index * 24;
let a = this._texCoordArr;
a[i + 3] = 0;
a[i + 7] = 0;
a[i + 11] = 0;
a[i + 15] = 0;
a[i + 19] = 0;
a[i + 23] = 0;
this._setChangedBuffer(TEXCOORD_BUFFER);
}
public setTexOffsetArr(index: number, value: number) {
let i = index * 6;
let a = this._texOffsetArr;
a[i] = value;
a[i + 1] = value;
a[i + 2] = value;
a[i + 3] = value;
a[i + 4] = value;
a[i + 5] = value;
this._setChangedBuffer(TEXOFFSET_BUFFER);
}
public setStrokeSizeArr(index: number, value: number) {
let i = index * 6;
let a = this._strokeSizeArr;
a[i] = value;
a[i + 1] = value;
a[i + 2] = value;
a[i + 3] = value;
a[i + 4] = value;
a[i + 5] = value;
this._setChangedBuffer(STROKESIZE_BUFFER);
}
public refreshTexCoordsArr() {
let bc = this._entityCollection;
if (bc && this._renderer) {
let ta = this._renderer.strokeTextureAtlas;
for (let i = 0; i < this._rays.length; i++) {
let ri = this._rays[i];
let img = ri.getImage();
if (img) {
let taData = ta.get(img.__nodeIndex!);
if (taData) {
this.setTexCoordArr(ri._handlerIndex, taData.texCoords);
}
}
}
}
}
}
export { RayHandler };