save
This commit is contained in:
parent
a5a8735cac
commit
9a1642633f
@ -1,3 +0,0 @@
|
|||||||
import { reactive } from "vue";
|
|
||||||
|
|
||||||
export const signalModal = reactive();
|
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="">
|
<div class="">
|
||||||
<el-radio-group v-model="signalModal">
|
<el-radio-group v-model="signalModal"
|
||||||
|
@click="onRadioClick"
|
||||||
|
>
|
||||||
<!-- 数字模式 -->
|
<!-- 数字模式 -->
|
||||||
<el-radio-button :label="0">
|
<el-radio-button :label="0">
|
||||||
<el-tooltip
|
<el-tooltip
|
||||||
@ -37,16 +39,41 @@
|
|||||||
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineComponent, ref } from 'vue';
|
import { globalLookup } from '@/hook/global';
|
||||||
|
import { defineComponent, nextTick, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
// 负责展示波形形式的模块,分为数字形式、折线模拟形式、阶梯模拟形式
|
// 负责展示波形形式的模块,分为数字形式、折线模拟形式、阶梯模拟形式
|
||||||
defineComponent({ name: 'signal-modal' });
|
defineComponent({ name: 'signal-modal' });
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const signalModal = ref(0);
|
const signalModal = ref(0);
|
||||||
|
|
||||||
|
|
||||||
|
function getOneSelectLink() {
|
||||||
|
let selectedLink = undefined;
|
||||||
|
for (const link of globalLookup.sidebarSelectedWireLinks) {
|
||||||
|
selectedLink = link;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return selectedLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
watch(globalLookup.sidebarSelectedWireLinks, () => {
|
||||||
|
const link = getOneSelectLink();
|
||||||
|
if (link) {
|
||||||
|
const option = globalLookup.currentSignalRenderOptions.get(link);
|
||||||
|
if (option && typeof option.renderModal === 'number') {
|
||||||
|
signalModal.value = option.renderModal;
|
||||||
|
} else {
|
||||||
|
signalModal.value = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -21,7 +21,7 @@ class ShaderMaker {
|
|||||||
gl.compileShader(shader);
|
gl.compileShader(shader);
|
||||||
const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
const ok = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
console.log('创建类型为 ' + type + ' 的着色器失败!');
|
console.log('创建类型为 ' + this.type + ' 的着色器失败!');
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
@ -30,8 +30,10 @@ class ShaderMaker {
|
|||||||
const colorsLength = gl_Colors_template.length << 1;
|
const colorsLength = gl_Colors_template.length << 1;
|
||||||
|
|
||||||
const vertexShader = new ShaderMaker('VERTEX_SHADER', `#version 300 es
|
const vertexShader = new ShaderMaker('VERTEX_SHADER', `#version 300 es
|
||||||
in uvec4 pos;
|
in ivec2 pos;
|
||||||
|
in ivec3 control;
|
||||||
out vec4 v_color;
|
out vec4 v_color;
|
||||||
|
uniform float posYFactor;
|
||||||
uniform vec2 scale;
|
uniform vec2 scale;
|
||||||
uniform vec2 offset;
|
uniform vec2 offset;
|
||||||
uniform vec4 colors[${colorsLength}];
|
uniform vec4 colors[${colorsLength}];
|
||||||
@ -39,14 +41,24 @@ uniform vec2 shifts[7]; // 基础八位图偏移量,为了性能,po
|
|||||||
uniform vec2 widthShifts[8]; // 用于构造线宽的偏移
|
uniform vec2 widthShifts[8]; // 用于构造线宽的偏移
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_color = colors[pos.z];
|
vec2 shift = shifts[control.x];
|
||||||
vec2 shift = shifts[pos.y];
|
vec2 ws = widthShifts[control.y];
|
||||||
vec2 widthShift = widthShifts[pos.w];
|
v_color = colors[control.z];
|
||||||
gl_Position = vec4(
|
|
||||||
float(pos.x) * scale.x + offset.x + float(widthShift.x) + shift.y,
|
// 为了性能,传递进来进来的都是整数,pos.y 需要除以 posYFactor
|
||||||
float(shift.x) * scale.y + offset.y + float(widthShift.y),
|
float posX = float(pos.x);
|
||||||
1, 1
|
float posY = float(pos.y) / posYFactor;
|
||||||
);
|
|
||||||
|
// 偏移包括三部分:用户滚动时发生的全局位移、为了设置线宽发生的位移、与 scale 无关的额外位移
|
||||||
|
float offsetX = offset.x + float(ws.x) + float(shift.x);
|
||||||
|
float offsetY = offset.y + float(ws.y) + float(shift.y);
|
||||||
|
|
||||||
|
gl_Position = vec4(
|
||||||
|
posX * scale.x + offsetX,
|
||||||
|
posY * scale.y + offsetY,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
);
|
||||||
}`);
|
}`);
|
||||||
|
|
||||||
const fragmentShader = new ShaderMaker('FRAGMENT_SHADER', `#version 300 es
|
const fragmentShader = new ShaderMaker('FRAGMENT_SHADER', `#version 300 es
|
||||||
|
@ -88,24 +88,24 @@ const gl_Shifts = new Float32Array([ // 14
|
|||||||
-1, 0 // 6
|
-1, 0 // 6
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 视屏幕本身而定
|
||||||
|
const posYFactor = 10000;
|
||||||
|
const glslInputLength = 5;
|
||||||
|
|
||||||
// 为了满足 vec 类型的波形的开头和结尾的那个小小的内嵌的、不受scale影响的值
|
// 为了满足 vec 类型的波形的开头和结尾的那个小小的内嵌的、不受scale影响的值
|
||||||
// 第一列 Y 第二列 X 在所有计算完成后的额外偏移量
|
// 第一列 Y 第二列 X 在所有计算完成后的额外偏移量
|
||||||
const barShift = 0.004;
|
const barShift = 0.004;
|
||||||
|
|
||||||
const gl_Shifts_for_bar = new Float32Array([
|
const gl_Shifts_for_bar = new Float32Array([
|
||||||
0, 0, // 0
|
0, 0, // 0
|
||||||
1, barShift, // 1
|
barShift, 0, // 1
|
||||||
1, -barShift, // 2
|
-barShift, 0, // 2
|
||||||
1, 0, // 3
|
0, 0, // 3
|
||||||
-1, barShift, // 4
|
barShift, 0, // 4
|
||||||
-1, -barShift, // 5
|
-barShift, 0, // 5
|
||||||
-1, 0 // 6
|
0, 0, // 6
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const gl_Shifts_map = new Map();
|
|
||||||
gl_Shifts_map.set(-1, 4);
|
|
||||||
gl_Shifts_map.set(0, 0);
|
|
||||||
gl_Shifts_map.set(1, 1);
|
|
||||||
|
|
||||||
const lineWidth = 0.004 * 3800 / screenWidthPixel; // 不能写为 0.0045 这样会因为插值造成不同线段的宽度不一致的问题
|
const lineWidth = 0.004 * 3800 / screenWidthPixel; // 不能写为 0.0045 这样会因为插值造成不同线段的宽度不一致的问题
|
||||||
const widthShift = 0.002;
|
const widthShift = 0.002;
|
||||||
@ -120,16 +120,33 @@ const gl_WidthShifts = new Float32Array([
|
|||||||
widthShift, widthShift // 7
|
widthShift, widthShift // 7
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
function prettyPrint(array) {
|
||||||
|
const stack = [];
|
||||||
|
for (const num of array) {
|
||||||
|
if (stack.length === 5) {
|
||||||
|
console.log(stack);
|
||||||
|
stack.length = 0;
|
||||||
|
}
|
||||||
|
stack.push(num);
|
||||||
|
}
|
||||||
|
if (stack.length > 0) {
|
||||||
|
console.log(stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getRatio,
|
getRatio,
|
||||||
gl_Colors,
|
gl_Colors,
|
||||||
gl_Shifts,
|
gl_Shifts,
|
||||||
|
posYFactor,
|
||||||
lineWidth,
|
lineWidth,
|
||||||
widthShift,
|
widthShift,
|
||||||
gl_WidthShifts,
|
gl_WidthShifts,
|
||||||
gl_Shifts_map,
|
|
||||||
screenWidthPixel,
|
screenWidthPixel,
|
||||||
screenHeightPixel,
|
screenHeightPixel,
|
||||||
gl_Shifts_for_bar,
|
gl_Shifts_for_bar,
|
||||||
barShift
|
barShift,
|
||||||
|
glslInputLength,
|
||||||
|
prettyPrint
|
||||||
};
|
};
|
@ -1,8 +1,8 @@
|
|||||||
import { globalSetting, globalStyle } from '../global';
|
import { globalSetting, globalStyle } from '../global';
|
||||||
|
|
||||||
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_Shifts_map, gl_WidthShifts, barShift, getRatio, screenHeightPixel, maskColorIndexOffset } from './render-utils.js';
|
import { gl_Colors, gl_Shifts, gl_Shifts_for_bar, gl_WidthShifts, barShift, getRatio, screenHeightPixel, maskColorIndexOffset, posYFactor, glslInputLength, prettyPrint } from './render-utils.js';
|
||||||
import { vertexShader, fragmentShader } from './render-shader.js';
|
import { vertexShader, fragmentShader } from './render-shader.js';
|
||||||
import { renderAsCommonDigital } from './toolbar/renderModal';
|
import { renderAsBit, renderAsCommonDigital, renderAsLadderAnalog } from './toolbar/renderModal';
|
||||||
|
|
||||||
// const { ChangoItem } = require('./types.d.ts');
|
// const { ChangoItem } = require('./types.d.ts');
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ class WebGL2WaveRender {
|
|||||||
* scale: WebGLUniformLocation,
|
* scale: WebGLUniformLocation,
|
||||||
* offset: WebGLUniformLocation,
|
* offset: WebGLUniformLocation,
|
||||||
* pos: number,
|
* pos: number,
|
||||||
|
* control: number,
|
||||||
* widthShifts: WebGLUniformLocation,
|
* widthShifts: WebGLUniformLocation,
|
||||||
* gl: WebGL2RenderingContext
|
* gl: WebGL2RenderingContext
|
||||||
* }}
|
* }}
|
||||||
@ -61,9 +62,11 @@ class WebGL2WaveRender {
|
|||||||
const webglLocation = {
|
const webglLocation = {
|
||||||
colors: gl.getUniformLocation(program, 'colors'),
|
colors: gl.getUniformLocation(program, 'colors'),
|
||||||
shifts: gl.getUniformLocation(program, 'shifts'),
|
shifts: gl.getUniformLocation(program, 'shifts'),
|
||||||
|
posYFactor: gl.getUniformLocation(program, 'posYFactor'),
|
||||||
scale: gl.getUniformLocation(program, 'scale'),
|
scale: gl.getUniformLocation(program, 'scale'),
|
||||||
offset: gl.getUniformLocation(program, 'offset'),
|
offset: gl.getUniformLocation(program, 'offset'),
|
||||||
pos: gl.getAttribLocation(program, 'pos'),
|
pos: gl.getAttribLocation(program, 'pos'),
|
||||||
|
control: gl.getAttribLocation(program, 'control'),
|
||||||
widthShifts: gl.getUniformLocation(program, 'widthShifts'),
|
widthShifts: gl.getUniformLocation(program, 'widthShifts'),
|
||||||
gl
|
gl
|
||||||
};
|
};
|
||||||
@ -74,8 +77,8 @@ class WebGL2WaveRender {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* lineVerticesMap: Map<string, Uint32Array>,
|
* lineVerticesMap: Map<string, Int32Array>,
|
||||||
* maskVerticesMap: Map<string, Uint32Array>
|
* maskVerticesMap: Map<string, Int32Array>
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
makeVertex() {
|
makeVertex() {
|
||||||
@ -98,8 +101,8 @@ class WebGL2WaveRender {
|
|||||||
*
|
*
|
||||||
* @param {string} id 波形的 link
|
* @param {string} id 波形的 link
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* lineVertices: Uint32Array
|
* lineVertices: Int32Array
|
||||||
* maskVertices: Uint32Array
|
* maskVertices: Int32Array
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
makeVertexByID(id) {
|
makeVertexByID(id) {
|
||||||
@ -122,239 +125,27 @@ class WebGL2WaveRender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 将 bit 类型的 wave 的值转化为渲染需要用到的值
|
|
||||||
* @param {string} link
|
|
||||||
* @param {number} value
|
|
||||||
* @return {{
|
|
||||||
* y: number // 裁剪空间的纵坐标
|
|
||||||
* color: number // 颜色的索引 颜色rgb = gl_Colors[color]
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
translateValue2RenderParameter(link, value) {
|
|
||||||
let colorParam;
|
|
||||||
switch (value) {
|
|
||||||
case 0: colorParam = { y: -1, color: 2 }; break; // 0 value
|
|
||||||
case 1: colorParam = { y: 1, color: 3 }; break; // 1 value
|
|
||||||
case 2: case 3: colorParam = { y: -1, color: 4 }; break; // 不定态 x
|
|
||||||
case 4: case 5: colorParam = { y: 0, color: 2 }; break; // 高阻态 z
|
|
||||||
default: colorParam = { y: -1, color: 7 }; break; // 其他,我也不知道还有啥
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === 0 || value === 1) {
|
|
||||||
const renderOptions = this.globalLookup.currentSignalRenderOptions;
|
|
||||||
if (renderOptions.has(link)) {
|
|
||||||
const option = renderOptions.get(link);
|
|
||||||
if (typeof option.color === 'number') {
|
|
||||||
colorParam.color = option.color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return colorParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {{x: number, y: number, color: number} | undefined} p0 前一个点
|
|
||||||
* @param {{x: number, y: number, color: number} | undefined} p1 当前的点
|
|
||||||
* @param {{x: number, y: number, color: number} | undefined} p2 后一个点
|
|
||||||
* @returns {number} 这是 widthshift 的索引,只需要 + 4 再 % 8 就能得到另一个
|
|
||||||
*/
|
|
||||||
makeWidthShiftIndexByPoints(p0, p1, p2) {
|
|
||||||
if (p0 === undefined) {
|
|
||||||
if (p1.y === p2.y) {
|
|
||||||
return 0;
|
|
||||||
} else if (p1.x === p2.x) {
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
} else if (p2 === undefined) {
|
|
||||||
if (p1.y === p0.y) {
|
|
||||||
return 0;
|
|
||||||
} else if (p1.x === p0.x) {
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (p0.x !== p1.x && p0.y === p1.y && p1.x === p2.x && p1.y !== p2.y) {
|
|
||||||
if (p2.y > p1.y) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
} else if (p0.x === p1.x && p0.y !== p1.y && p1.x !== p2.x && p1.y === p2.y) {
|
|
||||||
if (p1.y > p0.y) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number} x1
|
|
||||||
* @param {number} y1
|
|
||||||
* @param {number} x2
|
|
||||||
* @param {number} y2
|
|
||||||
* @param {number} color
|
|
||||||
* @param {number} wsIndex
|
|
||||||
* @returns {number[]}
|
|
||||||
*/
|
|
||||||
makeRectangleVertices(x1, y1, x2, y2, color, wsIndex = 0) {
|
|
||||||
const r1 = [x1, gl_Shifts_map.get(y2), color, wsIndex];
|
|
||||||
const r2 = [x1, gl_Shifts_map.get(y1), color, wsIndex];
|
|
||||||
const r3 = [x2, gl_Shifts_map.get(y1), color, wsIndex];
|
|
||||||
const r4 = [x2, gl_Shifts_map.get(y2), color, wsIndex];
|
|
||||||
return this.makeQuadVertices(r1, r2, r3, r4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number[]} p1
|
|
||||||
* @param {number[]} p2
|
|
||||||
* @param {number[]} p3
|
|
||||||
* @param {number[]} p4
|
|
||||||
* @returns {number[]}
|
|
||||||
*/
|
|
||||||
makeQuadVertices(p1, p2, p3, p4) {
|
|
||||||
return [
|
|
||||||
...p1, ...p2, ...p3,
|
|
||||||
...p1, ...p3, ...p4
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} link
|
* @param {string} link
|
||||||
* @param {Array<string | number>} wave
|
* @param {Array<string | number>} wave
|
||||||
* @param { number } time
|
* @param { number } time
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* lineVertices: Uint32Array
|
* lineVertices: Int32Array
|
||||||
* maskVertices: Uint32Array
|
* maskVertices: Int32Array
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
makeBitVertex(link, wave, time, debug = false) {
|
makeBitVertex(link, wave, time, debug = false) {
|
||||||
const length = wave.length;
|
|
||||||
// 先将节点数据转化为裁剪空间的坐标
|
|
||||||
const perspectivePoints = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < length; ++ i) {
|
const { lineVertices, maskVertices } = renderAsBit(link, wave, time);
|
||||||
// const currentWave = wave[(i === 0) ? 0 : (i - 1)];
|
|
||||||
const currentWave = wave[i];
|
|
||||||
const nextWave = (i === (length - 1)) ? wave[i] : wave[i + 1];
|
|
||||||
|
|
||||||
const t1 = currentWave[0];
|
|
||||||
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
|
||||||
const value1 = currentWave[1];
|
|
||||||
const value2 = nextWave[1];
|
|
||||||
|
|
||||||
const renderParam1 = this.translateValue2RenderParameter(link, value1);
|
|
||||||
const renderParam2 = this.translateValue2RenderParameter(link, value2);
|
|
||||||
|
|
||||||
if (i === 0) {
|
|
||||||
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
|
||||||
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
|
||||||
} else {
|
|
||||||
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
|
||||||
if ((lastPoint.y !== renderParam1.y) || (lastPoint.color !== renderParam1.color)) {
|
|
||||||
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
|
||||||
}
|
|
||||||
if ((renderParam1.y !== renderParam2.y) || (renderParam1.color !== renderParam2.color)) {
|
|
||||||
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保最后一个点延申到了 time
|
|
||||||
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
|
||||||
if (lastPoint.x < time) {
|
|
||||||
perspectivePoints.push({ x: time, y: lastPoint.y, color: lastPoint.color });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算出传入 shader 四元组数组
|
|
||||||
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
|
||||||
const pointNum = perspectivePoints.length;
|
|
||||||
const lineVertices = [];
|
|
||||||
const maskVertices = [];
|
|
||||||
|
|
||||||
|
|
||||||
// 制作 lineVertices
|
|
||||||
for (let i = 0; i < pointNum; ++ i) {
|
|
||||||
// p0: 上一个点
|
|
||||||
// p1: 当前的点
|
|
||||||
// p2: 下一个点
|
|
||||||
const p0 = perspectivePoints[i - 1];
|
|
||||||
const p1 = perspectivePoints[i];
|
|
||||||
const p2 = perspectivePoints[i + 1];
|
|
||||||
// p1.x, y1Index, p1.color, 0,
|
|
||||||
const y1Index = gl_Shifts_map.get(p1.y);
|
|
||||||
|
|
||||||
const wsIndex = this.makeWidthShiftIndexByPoints(p0, p1, p2);
|
|
||||||
|
|
||||||
if (wsIndex === undefined) {
|
|
||||||
console.log(p0, p1, p2);
|
|
||||||
}
|
|
||||||
|
|
||||||
lineVertices.push(
|
|
||||||
p1.x, y1Index, p1.color, wsIndex,
|
|
||||||
p1.x, y1Index, p1.color, (wsIndex + 4) % 8
|
|
||||||
);
|
|
||||||
|
|
||||||
// 防止颜色不同导致单个图元内出现两个颜色,这会引发shader的渐变
|
|
||||||
if (p2 !== undefined && p1.color !== p2.color) {
|
|
||||||
lineVertices.push(
|
|
||||||
p1.x, y1Index, p2.color, wsIndex,
|
|
||||||
p1.x, y1Index, p2.color, (wsIndex + 4) % 8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 制作 maskVertices
|
|
||||||
for (let i = 0; i < pointNum; ++ i) {
|
|
||||||
const p1 = perspectivePoints[i];
|
|
||||||
|
|
||||||
// 开头就有一条线
|
|
||||||
if (i === 0 && p1.y === 1) {
|
|
||||||
while (perspectivePoints[++ i] && perspectivePoints[i].y === 1);
|
|
||||||
// 回退
|
|
||||||
if (-- i > 0) {
|
|
||||||
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
|
||||||
const rectangleVertices = this.makeRectangleVertices(p1.x, 1, perspectivePoints[i].x, -1, p1.color + maskColorIndexOffset, 4);
|
|
||||||
// 三角图元画矩形
|
|
||||||
maskVertices.push(...rectangleVertices);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上升沿才使用
|
|
||||||
const p2 = perspectivePoints[i + 1];
|
|
||||||
const p3 = perspectivePoints[i + 2];
|
|
||||||
|
|
||||||
if (p1 === undefined || p2 === undefined || p3 === undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (p2.y > p1.y) {
|
|
||||||
// 矩形的四个点
|
|
||||||
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
|
||||||
const rectangleVertices = this.makeRectangleVertices(p2.x, p2.y, p3.x, p1.y, p2.color + maskColorIndexOffset, 4);
|
|
||||||
// 三角图元画矩形
|
|
||||||
maskVertices.push(...rectangleVertices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log(perspectivePoints);
|
|
||||||
console.log(pointNum);
|
|
||||||
console.log(lineVertices);
|
console.log(lineVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lineVertices : new Uint32Array(lineVertices),
|
lineVertices : new Int32Array(lineVertices),
|
||||||
maskVertices : new Uint32Array(maskVertices)
|
maskVertices : new Int32Array(maskVertices)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,12 +155,13 @@ class WebGL2WaveRender {
|
|||||||
* @param {Array<string | number>} wave
|
* @param {Array<string | number>} wave
|
||||||
* @param { number } time
|
* @param { number } time
|
||||||
* @returns {{
|
* @returns {{
|
||||||
* lineVertices: Uint32Array
|
* lineVertices: Int32Array
|
||||||
* maskVertices: Uint32Array
|
* maskVertices: Int32Array
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
makeVecVertex(link, wave, time, debug = false) {
|
makeVecVertex(link, wave, time, debug = false) {
|
||||||
const lookup = this.globalLookup;
|
const lookup = this.globalLookup;
|
||||||
|
|
||||||
const { lineVertices, maskVertices } = renderAsCommonDigital(lookup, link, wave, time);
|
const { lineVertices, maskVertices } = renderAsCommonDigital(lookup, link, wave, time);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
@ -377,13 +169,24 @@ class WebGL2WaveRender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lineVertices: new Uint32Array(lineVertices),
|
lineVertices: new Int32Array(lineVertices),
|
||||||
maskVertices: new Uint32Array(maskVertices)
|
maskVertices: new Int32Array(maskVertices)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setShaderInput() {
|
||||||
|
const UIntSize = Int32Array.BYTES_PER_ELEMENT; // 4
|
||||||
|
const webglLocation = this.webglLocation;
|
||||||
|
const gl = webglLocation.gl;
|
||||||
|
|
||||||
|
gl.vertexAttribIPointer(webglLocation.pos, 2, gl.INT, 5 * UIntSize, 0);
|
||||||
|
gl.vertexAttribIPointer(webglLocation.control, 3, gl.INT, 5 * UIntSize, 2 * UIntSize);
|
||||||
|
gl.enableVertexAttribArray(webglLocation.pos);
|
||||||
|
gl.enableVertexAttribArray(webglLocation.control);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @description 根据 id (link) 将对应信号的 value 数据转换成对应视图的 VAO 以供 webgl 渲染
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
@ -407,8 +210,7 @@ class WebGL2WaveRender {
|
|||||||
gl.bufferData(gl.ARRAY_BUFFER, lineVertices, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, lineVertices, gl.STATIC_DRAW);
|
||||||
signalItem.lineVao = gl.createVertexArray();
|
signalItem.lineVao = gl.createVertexArray();
|
||||||
gl.bindVertexArray(signalItem.lineVao);
|
gl.bindVertexArray(signalItem.lineVao);
|
||||||
gl.vertexAttribIPointer(webglLocation.pos, 4, gl.UNSIGNED_INT, 0, 0);
|
this.setShaderInput();
|
||||||
gl.enableVertexAttribArray(webglLocation.pos);
|
|
||||||
|
|
||||||
// 创建并设置 绘制wave半透明遮罩层 主体轮廓的 缓冲区、vao、顶点设置
|
// 创建并设置 绘制wave半透明遮罩层 主体轮廓的 缓冲区、vao、顶点设置
|
||||||
const maskVertexBuffer = gl.createBuffer();
|
const maskVertexBuffer = gl.createBuffer();
|
||||||
@ -416,8 +218,7 @@ class WebGL2WaveRender {
|
|||||||
gl.bufferData(gl.ARRAY_BUFFER, maskVertices, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, maskVertices, gl.STATIC_DRAW);
|
||||||
signalItem.maskVao = gl.createVertexArray();
|
signalItem.maskVao = gl.createVertexArray();
|
||||||
gl.bindVertexArray(signalItem.maskVao);
|
gl.bindVertexArray(signalItem.maskVao);
|
||||||
gl.vertexAttribIPointer(webglLocation.pos, 4, gl.UNSIGNED_INT, 0, 0);
|
this.setShaderInput();
|
||||||
gl.enableVertexAttribArray(webglLocation.pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -439,8 +240,7 @@ class WebGL2WaveRender {
|
|||||||
gl.bufferData(gl.ARRAY_BUFFER, lineVertices, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, lineVertices, gl.STATIC_DRAW);
|
||||||
signalItem.lineVao = gl.createVertexArray();
|
signalItem.lineVao = gl.createVertexArray();
|
||||||
gl.bindVertexArray(signalItem.lineVao);
|
gl.bindVertexArray(signalItem.lineVao);
|
||||||
gl.vertexAttribIPointer(webglLocation.pos, 4, gl.UNSIGNED_INT, 0, 0);
|
this.setShaderInput();
|
||||||
gl.enableVertexAttribArray(webglLocation.pos);
|
|
||||||
|
|
||||||
// 创建并设置 绘制wave半透明遮罩层 主体轮廓的 缓冲区、vao、顶点设置
|
// 创建并设置 绘制wave半透明遮罩层 主体轮廓的 缓冲区、vao、顶点设置
|
||||||
const maskVertexBuffer = gl.createBuffer();
|
const maskVertexBuffer = gl.createBuffer();
|
||||||
@ -448,8 +248,7 @@ class WebGL2WaveRender {
|
|||||||
gl.bufferData(gl.ARRAY_BUFFER, maskVertices, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, maskVertices, gl.STATIC_DRAW);
|
||||||
signalItem.maskVao = gl.createVertexArray();
|
signalItem.maskVao = gl.createVertexArray();
|
||||||
gl.bindVertexArray(signalItem.maskVao);
|
gl.bindVertexArray(signalItem.maskVao);
|
||||||
gl.vertexAttribIPointer(webglLocation.pos, 4, gl.UNSIGNED_INT, 0, 0);
|
this.setShaderInput();
|
||||||
gl.enableVertexAttribArray(webglLocation.pos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initData() {
|
initData() {
|
||||||
@ -464,6 +263,7 @@ class WebGL2WaveRender {
|
|||||||
gl.uniform4fv(webglLocation.colors, gl_Colors);
|
gl.uniform4fv(webglLocation.colors, gl_Colors);
|
||||||
gl.uniform2fv(webglLocation.widthShifts, gl_WidthShifts);
|
gl.uniform2fv(webglLocation.widthShifts, gl_WidthShifts);
|
||||||
gl.uniform2fv(webglLocation.shifts, gl_Shifts);
|
gl.uniform2fv(webglLocation.shifts, gl_Shifts);
|
||||||
|
gl.uniform1f(webglLocation.posYFactor, posYFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -574,7 +374,7 @@ class WebGL2WaveRender {
|
|||||||
|
|
||||||
// 设置 webgl 和 canvas 大小位置一致
|
// 设置 webgl 和 canvas 大小位置一致
|
||||||
gl.viewport(0, 0, canvasWidth, canvasHeight);
|
gl.viewport(0, 0, canvasWidth, canvasHeight);
|
||||||
// 清楚颜色缓冲区,也就是删除上一次的渲染结果
|
// 清除颜色缓冲区,也就是删除上一次的渲染结果
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
// 根据 currentWiresRenderView 视图渲染
|
// 根据 currentWiresRenderView 视图渲染
|
||||||
@ -626,18 +426,18 @@ class WebGL2WaveRender {
|
|||||||
// 如果是 width 为 1 的
|
// 如果是 width 为 1 的
|
||||||
gl.uniform2fv(webglLocation.shifts, gl_Shifts);
|
gl.uniform2fv(webglLocation.shifts, gl_Shifts);
|
||||||
gl.bindVertexArray(signalItem.lineVao);
|
gl.bindVertexArray(signalItem.lineVao);
|
||||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, lineVertices.length / 4);
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, lineVertices.length / glslInputLength);
|
||||||
|
|
||||||
gl.bindVertexArray(signalItem.maskVao);
|
gl.bindVertexArray(signalItem.maskVao);
|
||||||
gl.drawArrays(gl.TRIANGLES, 0, maskVertices.length / 4);
|
gl.drawArrays(gl.TRIANGLES, 0, maskVertices.length / glslInputLength);
|
||||||
} else {
|
} else {
|
||||||
// 如果是 width 大于 1 的
|
// 如果是 width 大于 1 的
|
||||||
gl.uniform2fv(webglLocation.shifts, gl_Shifts_for_bar);
|
gl.uniform2fv(webglLocation.shifts, gl_Shifts_for_bar);
|
||||||
gl.bindVertexArray(signalItem.lineVao);
|
gl.bindVertexArray(signalItem.lineVao);
|
||||||
gl.drawArrays(gl.TRIANGLES, 0, lineVertices.length / 4);
|
gl.drawArrays(gl.TRIANGLES, 0, lineVertices.length / glslInputLength);
|
||||||
|
|
||||||
gl.bindVertexArray(signalItem.maskVao);
|
gl.bindVertexArray(signalItem.maskVao);
|
||||||
gl.drawArrays(gl.TRIANGLES, 0, maskVertices.length / 4);
|
gl.drawArrays(gl.TRIANGLES, 0, maskVertices.length / glslInputLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,23 @@
|
|||||||
* @property {number} minVal
|
* @property {number} minVal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { maskColorIndexOffset } from "../render-utils";
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} BitRenderTempStruct
|
||||||
|
* @property {number} color 颜色的索引 颜色rgb = gl_Colors[color]
|
||||||
|
* @property {number} y 裁剪空间的纵坐标
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description
|
||||||
|
* @typedef {Object} BitRenderHandlePoint
|
||||||
|
* @property {number} x
|
||||||
|
* @property {number} y
|
||||||
|
* @property {number} color
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { globalLookup } from "@/hook/global";
|
||||||
|
import { maskColorIndexOffset, posYFactor } from "../render-utils";
|
||||||
import { hexToSignedInt } from "./renderFormat";
|
import { hexToSignedInt } from "./renderFormat";
|
||||||
|
|
||||||
|
|
||||||
@ -24,6 +40,227 @@ function makeQuadVertices(p1, p2, p3, p4) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} x1
|
||||||
|
* @param {number} y1
|
||||||
|
* @param {number} x2
|
||||||
|
* @param {number} y2
|
||||||
|
* @param {number} color
|
||||||
|
* @param {number} wsIndex
|
||||||
|
* @returns {number[]}
|
||||||
|
*/
|
||||||
|
function makeRectangleVertices(x1, y1, x2, y2, color, wsIndex = 0) {
|
||||||
|
// uvec2 pos; uvec3 control;
|
||||||
|
const r1 = [x1, y2 * posYFactor, 0, wsIndex, color];
|
||||||
|
const r2 = [x1, y1 * posYFactor, 0, wsIndex, color];
|
||||||
|
const r3 = [x2, y1 * posYFactor, 0, wsIndex, color];
|
||||||
|
const r4 = [x2, y2 * posYFactor, 0, wsIndex, color];
|
||||||
|
return makeQuadVertices(r1, r2, r3, r4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 bit 类型的 wave 的值转化为渲染需要用到的值
|
||||||
|
* @param {string} link
|
||||||
|
* @param {number[]} wave
|
||||||
|
* @param {number} time
|
||||||
|
* @return {BitRenderTempStruct}
|
||||||
|
*/
|
||||||
|
function makeBitRenderParam(link, wave, time) {
|
||||||
|
const value = wave[1];
|
||||||
|
let colorParam;
|
||||||
|
switch (value) {
|
||||||
|
case 0: colorParam = { y: -1, color: 2 }; break; // 0 value
|
||||||
|
case 1: colorParam = { y: 1, color: 3 }; break; // 1 value
|
||||||
|
case 2: case 3: colorParam = { y: -1, color: 4 }; break; // 不定态 x
|
||||||
|
case 4: case 5: colorParam = { y: 0, color: 2 }; break; // 高阻态 z
|
||||||
|
default: colorParam = { y: -1, color: 7 }; break; // 其他,我也不知道还有啥
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === 0 || value === 1) {
|
||||||
|
const renderOptions = globalLookup.currentSignalRenderOptions;
|
||||||
|
if (renderOptions.has(link)) {
|
||||||
|
const option = renderOptions.get(link);
|
||||||
|
if (typeof option.color === 'number') {
|
||||||
|
colorParam.color = option.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {BitRenderHandlePoint | undefined} p0 前一个点
|
||||||
|
* @param {BitRenderHandlePoint | undefined} p1 当前的点
|
||||||
|
* @param {BitRenderHandlePoint | undefined} p2 后一个点
|
||||||
|
* @returns {number} 这是 widthshift 的索引,只需要 + 4 再 % 8 就能得到另一个
|
||||||
|
*/
|
||||||
|
function makeWidthShiftIndexByPoints(p0, p1, p2) {
|
||||||
|
if (p0 === undefined) {
|
||||||
|
if (p1.y === p2.y) {
|
||||||
|
return 0;
|
||||||
|
} else if (p1.x === p2.x) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
} else if (p2 === undefined) {
|
||||||
|
if (p1.y === p0.y) {
|
||||||
|
return 0;
|
||||||
|
} else if (p1.x === p0.x) {
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (p0.x !== p1.x && p0.y === p1.y && p1.x === p2.x && p1.y !== p2.y) {
|
||||||
|
if (p2.y > p1.y) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
} else if (p0.x === p1.x && p0.y !== p1.y && p1.x !== p2.x && p1.y === p2.y) {
|
||||||
|
if (p1.y > p0.y) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} link
|
||||||
|
* @param {Array<string | number>} wave
|
||||||
|
* @param { number } time
|
||||||
|
* @param {(link: string, wave: number[], time: number) => BitRenderTempStruct} renderParamMaker
|
||||||
|
* @returns {VecRenderNumberVertices}
|
||||||
|
*/
|
||||||
|
function renderBlockWave(link, wave, time, renderParamMaker) {
|
||||||
|
const length = wave.length;
|
||||||
|
// 先将节点数据转化为裁剪空间的坐标
|
||||||
|
const perspectivePoints = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < length; ++ i) {
|
||||||
|
// const currentWave = wave[(i === 0) ? 0 : (i - 1)];
|
||||||
|
const currentWave = wave[i];
|
||||||
|
const nextWave = (i === (length - 1)) ? wave[i] : wave[i + 1];
|
||||||
|
|
||||||
|
const t1 = currentWave[0];
|
||||||
|
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
||||||
|
const value1 = currentWave[1];
|
||||||
|
const value2 = nextWave[1];
|
||||||
|
|
||||||
|
const renderParam1 = renderParamMaker(link, currentWave, time);
|
||||||
|
const renderParam2 = renderParamMaker(link, nextWave, time);
|
||||||
|
|
||||||
|
if (i === 0) {
|
||||||
|
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
||||||
|
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
||||||
|
} else {
|
||||||
|
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
||||||
|
if ((lastPoint.y !== renderParam1.y) || (lastPoint.color !== renderParam1.color)) {
|
||||||
|
perspectivePoints.push({ x: t1, y: renderParam1.y, color: renderParam1.color });
|
||||||
|
}
|
||||||
|
if ((renderParam1.y !== renderParam2.y) || (renderParam1.color !== renderParam2.color)) {
|
||||||
|
perspectivePoints.push({ x: t2, y: renderParam1.y, color: renderParam1.color });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保最后一个点延申到了 time
|
||||||
|
const lastPoint = perspectivePoints[perspectivePoints.length - 1];
|
||||||
|
if (lastPoint.x < time) {
|
||||||
|
perspectivePoints.push({ x: time, y: lastPoint.y, color: lastPoint.color });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算出传入 shader 四元组数组
|
||||||
|
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
||||||
|
const pointNum = perspectivePoints.length;
|
||||||
|
const lineVertices = [];
|
||||||
|
const maskVertices = [];
|
||||||
|
|
||||||
|
|
||||||
|
// 制作 lineVertices
|
||||||
|
for (let i = 0; i < pointNum; ++ i) {
|
||||||
|
// p0: 上一个点
|
||||||
|
// p1: 当前的点
|
||||||
|
// p2: 下一个点
|
||||||
|
const p0 = perspectivePoints[i - 1];
|
||||||
|
const p1 = perspectivePoints[i];
|
||||||
|
const p2 = perspectivePoints[i + 1];
|
||||||
|
|
||||||
|
const wsIndex = makeWidthShiftIndexByPoints(p0, p1, p2);
|
||||||
|
|
||||||
|
if (wsIndex === undefined) {
|
||||||
|
console.log(p0, p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineVertices.push(
|
||||||
|
// uvec2 pos; uvec3 control;
|
||||||
|
p1.x, p1.y * posYFactor, 0, wsIndex, p1.color,
|
||||||
|
p1.x, p1.y * posYFactor, 0, (wsIndex + 4) % 8, p1.color
|
||||||
|
);
|
||||||
|
|
||||||
|
// 防止颜色不同导致单个图元内出现两个颜色,这会引发shader的渐变
|
||||||
|
if (p2 !== undefined && p1.color !== p2.color) {
|
||||||
|
lineVertices.push(
|
||||||
|
// uvec2 pos; uvec3 control;
|
||||||
|
p1.x, p1.y * posYFactor, 0, wsIndex, p2.color,
|
||||||
|
p1.x, p1.y * posYFactor, 0, (wsIndex + 4) % 8, p2.color,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 制作 maskVertices
|
||||||
|
for (let i = 0; i < pointNum; ++ i) {
|
||||||
|
const p1 = perspectivePoints[i];
|
||||||
|
|
||||||
|
// 开头就有一条线
|
||||||
|
if (i === 0 && p1.y === 1) {
|
||||||
|
while (perspectivePoints[++ i] && perspectivePoints[i].y === 1);
|
||||||
|
// 回退
|
||||||
|
if (-- i > 0) {
|
||||||
|
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
||||||
|
const rectangleVertices = makeRectangleVertices(p1.x, 1, perspectivePoints[i].x, -1, p1.color + maskColorIndexOffset, 4);
|
||||||
|
// 三角图元画矩形
|
||||||
|
maskVertices.push(...rectangleVertices);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上升沿才使用
|
||||||
|
const p2 = perspectivePoints[i + 1];
|
||||||
|
const p3 = perspectivePoints[i + 2];
|
||||||
|
|
||||||
|
if (p1 === undefined || p2 === undefined || p3 === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (p2.y > p1.y) {
|
||||||
|
// 矩形的四个点
|
||||||
|
// 四元组: (x, yshift_index, color_index, width_shift_index)
|
||||||
|
const rectangleVertices = makeRectangleVertices(p2.x, p2.y, p3.x, p1.y, p2.color + maskColorIndexOffset, 4);
|
||||||
|
// 三角图元画矩形
|
||||||
|
maskVertices.push(...rectangleVertices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { lineVertices, maskVertices };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} link
|
||||||
|
* @param {Array<string | number>} wave
|
||||||
|
* @param { number } time
|
||||||
|
* @returns {VecRenderNumberVertices}
|
||||||
|
*/
|
||||||
|
export function renderAsBit(link, wave, time) {
|
||||||
|
return renderBlockWave(link, wave, time, makeBitRenderParam);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Digital
|
* @description Digital
|
||||||
* @param {GlobalLookup} lookup
|
* @param {GlobalLookup} lookup
|
||||||
@ -43,13 +280,13 @@ export function renderAsCommonDigital(lookup, link, wave, time) {
|
|||||||
|
|
||||||
// t1(val) --- t2(val)
|
// t1(val) --- t2(val)
|
||||||
// 详见 设计图 ./design/webgl.drawio makeVecVertex原理 sheet
|
// 详见 设计图 ./design/webgl.drawio makeVecVertex原理 sheet
|
||||||
// 此处的 y 不是 y 的索引,详见 gl_Shifts_for_bar 的设计
|
// 详见 gl_Shifts_for_bar 的设计
|
||||||
const p0 = {x: t1, y: 0};
|
const p0 = {x: t1, y: 0, shift: 0};
|
||||||
const p1 = {x: t2, y: 0};
|
const p1 = {x: t2, y: 0, shift: 0};
|
||||||
const a0 = {x: t1, y: 4};
|
const a0 = {x: t1, y: -1, shift: 4};
|
||||||
const a1 = {x: t2, y: 5};
|
const a1 = {x: t2, y: -1, shift: 5};
|
||||||
const a2 = {x: t1, y: 1};
|
const a2 = {x: t1, y: 1, shift: 1};
|
||||||
const a3 = {x: t2, y: 2};
|
const a3 = {x: t2, y: 1, shift: 2};
|
||||||
|
|
||||||
let color = 5;
|
let color = 5;
|
||||||
const renderOptions = lookup.currentSignalRenderOptions;
|
const renderOptions = lookup.currentSignalRenderOptions;
|
||||||
@ -70,10 +307,10 @@ export function renderAsCommonDigital(lookup, link, wave, time) {
|
|||||||
const preWsIndex = wsIndice[j];
|
const preWsIndex = wsIndice[j];
|
||||||
const nextWsIndex = wsIndice[(j + 1) % 6];
|
const nextWsIndex = wsIndice[(j + 1) % 6];
|
||||||
const quadVertices = makeQuadVertices(
|
const quadVertices = makeQuadVertices(
|
||||||
[prePoint.x, prePoint.y, color, preWsIndex],
|
[prePoint.x, prePoint.y * posYFactor, prePoint.shift, preWsIndex, color],
|
||||||
[prePoint.x, prePoint.y, color, (preWsIndex + 4) % 8],
|
[prePoint.x, prePoint.y * posYFactor, prePoint.shift, (preWsIndex + 4) % 8, color],
|
||||||
[nextPoint.x, nextPoint.y, color, (nextWsIndex + 4) % 8],
|
[nextPoint.x, nextPoint.y * posYFactor, nextPoint.shift, (nextWsIndex + 4) % 8, color],
|
||||||
[nextPoint.x, nextPoint.y, color, nextWsIndex],
|
[nextPoint.x, nextPoint.y * posYFactor, nextPoint.shift, nextWsIndex, color],
|
||||||
);
|
);
|
||||||
lineVertices.push(...quadVertices);
|
lineVertices.push(...quadVertices);
|
||||||
}
|
}
|
||||||
@ -91,9 +328,9 @@ export function renderAsCommonDigital(lookup, link, wave, time) {
|
|||||||
const point2 = points[i2];
|
const point2 = points[i2];
|
||||||
const point3 = points[i3];
|
const point3 = points[i3];
|
||||||
maskVertices.push(
|
maskVertices.push(
|
||||||
point1.x, point1.y, color + maskColorIndexOffset, wsIndice[i1],
|
point1.x, point1.y * posYFactor, point1.shift, wsIndice[i1], color + maskColorIndexOffset,
|
||||||
point2.x, point2.y, color + maskColorIndexOffset, wsIndice[i2],
|
point2.x, point2.y * posYFactor, point2.shift, wsIndice[i2], color + maskColorIndexOffset,
|
||||||
point3.x, point3.y, color + maskColorIndexOffset, wsIndice[i3]
|
point3.x, point3.y * posYFactor, point3.shift, wsIndice[i3], color + maskColorIndexOffset,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,9 +393,10 @@ function explainAsJSNumber(formatCode, val, width) {
|
|||||||
function getMaxMinByFormat(link, wave, time, formatCode, width) {
|
function getMaxMinByFormat(link, wave, time, formatCode, width) {
|
||||||
let maxVal = undefined;
|
let maxVal = undefined;
|
||||||
let minVal = undefined;
|
let minVal = undefined;
|
||||||
|
const length = wave.length;
|
||||||
|
|
||||||
// TODO : 优化这段代码
|
// TODO : 优化这段代码
|
||||||
for (let i = 0; i < wave.length; ++ i) {
|
for (let i = 0; i < length; ++ i) {
|
||||||
const [t1, val, mask] = wave[i];
|
const [t1, val, mask] = wave[i];
|
||||||
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
||||||
const numVal = explainAsJSNumber(formatCode, val, width);
|
const numVal = explainAsJSNumber(formatCode, val, width);
|
||||||
@ -189,11 +427,17 @@ function getMaxMinByFormat(link, wave, time, formatCode, width) {
|
|||||||
function getMappingFunc(formatCode, maxVal, minVal) {
|
function getMappingFunc(formatCode, maxVal, minVal) {
|
||||||
if (formatCode === 3) {
|
if (formatCode === 3) {
|
||||||
const maxAbs = Math.max(Math.abs(maxVal), Math.abs(minVal));
|
const maxAbs = Math.max(Math.abs(maxVal), Math.abs(minVal));
|
||||||
|
if (maxAbs === 0) {
|
||||||
|
return val => 0;
|
||||||
|
}
|
||||||
const k = 1 / maxAbs;
|
const k = 1 / maxAbs;
|
||||||
const b = -1;
|
const b = -1;
|
||||||
// 把 [-maxAbs, +maxAbs] 映射到 [-1, 1]
|
// 把 [-maxAbs, +maxAbs] 映射到 [-1, 1]
|
||||||
return val => k * (val + maxAbs) + b;
|
return val => k * (val + maxAbs) + b;
|
||||||
} else {
|
} else {
|
||||||
|
if (maxVal === 0) {
|
||||||
|
return val => -1;
|
||||||
|
}
|
||||||
const k = 2 / maxVal;
|
const k = 2 / maxVal;
|
||||||
const b = -1;
|
const b = -1;
|
||||||
// 把 [0, max] 映射到 [-1, 1]
|
// 把 [0, max] 映射到 [-1, 1]
|
||||||
@ -215,33 +459,39 @@ export function renderAsLadderAnalog(lookup, link, wave, time) {
|
|||||||
const signal = lookup.link2CurrentWires.get(link);
|
const signal = lookup.link2CurrentWires.get(link);
|
||||||
const width = signal.size;
|
const width = signal.size;
|
||||||
|
|
||||||
const { maxVal, minVal } = getMaxMinByFormat(lookup, link, wave, time, formatCode, width);
|
const { maxVal, minVal } = getMaxMinByFormat(link, wave, time, formatCode, width);
|
||||||
const coordinateTransform = getMappingFunc(formatCode, maxVal, minVal);
|
const coordinateTransform = getMappingFunc(formatCode, maxVal, minVal);
|
||||||
|
|
||||||
const length = wave.length;
|
const length = wave.length;
|
||||||
const lineVertices = [];
|
const lineVertices = [];
|
||||||
const maskVertices = [];
|
const maskVertices = [];
|
||||||
|
|
||||||
for (let i = 0; i < length; ++ i) {
|
function makeLadderAnalogRenderParam(link, wave, time) {
|
||||||
const [t1, val, mask] = wave[i];
|
const [t1, val, mask] = wave;
|
||||||
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
|
|
||||||
|
|
||||||
let color = 5;
|
|
||||||
if (mask) {
|
if (mask) {
|
||||||
color = 4;
|
// 不定态
|
||||||
} else if (renderOptions.has(link)) {
|
return { y: -1, color: 4 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据当前格式进行转换
|
||||||
|
const numVal = explainAsJSNumber(formatCode, val, width);
|
||||||
|
// 此时的 y 是一个 -1 到 1 的浮点数,因为 VAO 我设置了 Int
|
||||||
|
const y = coordinateTransform(numVal);
|
||||||
|
console.log(t1, y);
|
||||||
|
const colorParam = { y, color: 5 };
|
||||||
|
|
||||||
|
if (renderOptions.has(link)) {
|
||||||
const option = renderOptions.get(link);
|
const option = renderOptions.get(link);
|
||||||
if (typeof option.color === 'number') {
|
if (typeof option.color === 'number') {
|
||||||
color = option.color;
|
colorParam.color = option.color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return colorParam;
|
||||||
|
|
||||||
const numVal = explainAsJSNumber(formatCode, val, width);
|
|
||||||
const y = coordinateTransform(numVal);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return renderBlockWave(link, wave, time, makeLadderAnalogRenderParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,7 +505,11 @@ export function renderAsLadderAnalog(lookup, link, wave, time) {
|
|||||||
export function renderAsLineAnalog(lookup, link, wave, time) {
|
export function renderAsLineAnalog(lookup, link, wave, time) {
|
||||||
const renderOptions = lookup.currentSignalRenderOptions;
|
const renderOptions = lookup.currentSignalRenderOptions;
|
||||||
const formatCode = getValFormatCode(lookup, link);
|
const formatCode = getValFormatCode(lookup, link);
|
||||||
|
const signal = lookup.link2CurrentWires.get(link);
|
||||||
|
const width = signal.size;
|
||||||
|
|
||||||
|
const { maxVal, minVal } = getMaxMinByFormat(link, wave, time, formatCode, width);
|
||||||
|
|
||||||
|
|
||||||
const { maxVal, minVal } = getMaxMinByFormat(lookup, link, wave, time, formatCode);
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user