This commit is contained in:
锦恢 2024-08-22 22:39:20 +08:00
parent a5ae341b4e
commit 183185a57e
8 changed files with 4474 additions and 4251 deletions

View File

@ -96,7 +96,6 @@ onMounted(async () => {
worker.addEventListener('message', event => {
const workerVars = event.data;
console.log(workerVars);
const vcdInfo = workerVars.vcdInfo;
const signalValues = workerVars.signalValues;
@ -131,7 +130,6 @@ onMounted(async () => {
globalLookup.topModules.push(mod);
}
}
loading.close();
worker.terminate();
});

View File

@ -59,7 +59,7 @@ function handleColorSelector(index) {
const link = contextmenu.currentWire.link;
userSignalColorMap.set(link, index);
// VAO
globalLookup.waveRender.renderPipeHook.userDefinedColor = index;
globalLookup.setRenderOption(link, 'color', index);
globalLookup.waveRender.resetVertice(link);
globalLookup.render();
}

View File

@ -56,7 +56,7 @@ export const globalLookup = reactive({
/**
* @description 当前渲染的信号的基本选项比如高度颜色formatmodal 等等
* @type {Map<string, >}
* @type {Map<string, IRenderOption>}
*/
currentSignalRenderOptions: new Map(),
@ -117,6 +117,20 @@ export const globalLookup = reactive({
*/
getWaveRender() {
return this.waveRender;
},
/**
*
* @param {string} link
* @param {'height' | 'color' | 'valueFormat' | 'renderModal'} option
* @param {any} value
*/
setRenderOption(link, option, value) {
if (!this.currentSignalRenderOptions.has(link)) {
this.currentSignalRenderOptions.set(link, {});
}
const renderOption = this.currentSignalRenderOptions.get(link);
renderOption[option] = value;
}
});

View File

@ -2,6 +2,7 @@ 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 { vertexShader, fragmentShader } from './render-shader.js';
import { renderAsCommonDigital } from './toolbar/renderModal';
// const { ChangoItem } = require('./types.d.ts');
@ -23,12 +24,6 @@ class WebGL2WaveRender {
this.pstate = pstate;
this.plugins = plugins;
// 用于在外部进行额外特性更新使用的一个类,未来需要往渲染管线中添加量可以随时往里面加东西,然后
// 在管线相关的函数中去使用它
this.renderPipeHook = {
userDefinedColor: undefined
};
const gl = canvas.getContext('webgl2', {
premultipliedAlpha: false,
alpha: true,
@ -114,10 +109,10 @@ class WebGL2WaveRender {
const { kind, wave } = signalItem;
if (kind === 'bit') {
const { lineVertices, maskVertices } = this.makeBitVertex(wave, time);
const { lineVertices, maskVertices } = this.makeBitVertex(id, wave, time);
return { lineVertices, maskVertices };
} else if (kind === 'vec') {
const { lineVertices, maskVertices } = this.makeVecVertex(wave, time);
const { lineVertices, maskVertices } = this.makeVecVertex(id, wave, time);
return { lineVertices, maskVertices };
}
return {
@ -128,14 +123,15 @@ class WebGL2WaveRender {
/**
* @description 将wave 的值转化为渲染需要用到的值
* @param {*} value
* @description bit 类型的 wave 的值转化为渲染需要用到的值
* @param {string} link
* @param {number} value
* @return {{
* y: number // 裁剪空间的纵坐标
* color: number // 颜色的索引 颜色rgb = gl_Colors[color]
* }}
*/
translateValue2RenderParameter(value) {
translateValue2RenderParameter(link, value) {
let colorParam;
switch (value) {
case 0: colorParam = { y: -1, color: 2 }; break; // 0 value
@ -146,9 +142,12 @@ class WebGL2WaveRender {
}
if (value === 0 || value === 1) {
const renderPipeHook = this.renderPipeHook;
if (renderPipeHook.userDefinedColor !== undefined) {
colorParam.color = renderPipeHook.userDefinedColor;
const renderOptions = this.globalLookup.currentSignalRenderOptions;
if (renderOptions.has(link)) {
const option = renderOptions.get(link);
if (typeof option.color === 'number') {
colorParam.color = option.color;
}
}
}
@ -230,6 +229,7 @@ class WebGL2WaveRender {
/**
*
* @param {string} link
* @param {Array<string | number>} wave
* @param { number } time
* @returns {{
@ -237,7 +237,7 @@ class WebGL2WaveRender {
* maskVertices: Uint32Array
* }}
*/
makeBitVertex(wave, time, debug = false) {
makeBitVertex(link, wave, time, debug = false) {
const length = wave.length;
// 先将节点数据转化为裁剪空间的坐标
const perspectivePoints = [];
@ -252,8 +252,8 @@ class WebGL2WaveRender {
const value1 = currentWave[1];
const value2 = nextWave[1];
const renderParam1 = this.translateValue2RenderParameter(value1);
const renderParam2 = this.translateValue2RenderParameter(value2);
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 });
@ -360,7 +360,7 @@ class WebGL2WaveRender {
/**
*
* @param {string} link
* @param {Array<string | number>} wave
* @param { number } time
* @returns {{
@ -368,70 +368,9 @@ class WebGL2WaveRender {
* maskVertices: Uint32Array
* }}
*/
makeVecVertex(wave, time, debug = false) {
const lineVertices = [];
const maskVertices = [];
const length = wave.length;
const renderPipeHook = this.renderPipeHook;
for (let i = 0; i < length; ++ i) {
const [t1, val, mask] = wave[i];
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
// t1(val) --- t2(val)
// 详见 设计图 ./design/webgl.drawio makeVecVertex原理 sheet
// 此处的 y 不是 y 的索引,详见 gl_Shifts_for_bar 的设计
const p0 = {x: t1, y: 0};
const p1 = {x: t2, y: 0};
const a0 = {x: t1, y: 4};
const a1 = {x: t2, y: 5};
const a2 = {x: t1, y: 1};
const a3 = {x: t2, y: 2};
let color;
if (mask) {
color = 4;
} else if (renderPipeHook.userDefinedColor !== undefined){
color = renderPipeHook.userDefinedColor;
} else {
color = 5;
}
const points = [ a1, p1, a3, a2, p0, a0 ];
const wsIndice = [ 1, 2, 3, 5, 6, 7 ];
for (let i = 0; i < 6; ++ i) {
const prePoint = points[i];
const nextPoint = points[(i + 1) % 6];
const preWsIndex = wsIndice[i];
const nextWsIndex = wsIndice[(i + 1) % 6];
const quadVertices = this.makeQuadVertices(
[prePoint.x, prePoint.y, color, preWsIndex],
[prePoint.x, prePoint.y, color, (preWsIndex + 4) % 8],
[nextPoint.x, nextPoint.y, color, (nextWsIndex + 4) % 8],
[nextPoint.x, nextPoint.y, color, nextWsIndex],
);
lineVertices.push(...quadVertices);
}
const maskTriangles = [
[3, 4, 5],
[5, 0, 3],
[0, 3, 2],
[0, 1, 2]
];
for (const triangleIndice of maskTriangles) {
const [i1, i2, i3] = triangleIndice;
const point1 = points[i1];
const point2 = points[i2];
const point3 = points[i3];
maskVertices.push(
point1.x, point1.y, color + maskColorIndexOffset, wsIndice[i1],
point2.x, point2.y, color + maskColorIndexOffset, wsIndice[i2],
point3.x, point3.y, color + maskColorIndexOffset, wsIndice[i3]
);
}
}
makeVecVertex(link, wave, time, debug = false) {
const lookup = this.globalLookup;
const { lineVertices, maskVertices } = renderAsCommonDigital(lookup, link, wave, time);
if (debug) {
console.log(lineVertices);
@ -494,9 +433,6 @@ class WebGL2WaveRender {
this.lineVerticesMap.set(id, lineVertices);
this.maskVerticesMap.set(id, maskVertices);
// 清除自定义标志位
this.renderPipeHook.userDefinedColor = undefined;
// 创建并设置 绘制wave轮廓 主体轮廓的 缓冲区、vao、顶点设置
const lineVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, lineVertexBuffer);

View File

@ -0,0 +1,13 @@
export function hexToSignedInt(hex) {
if (hex.length % 2 != 0) {
hex = "0" + hex;
}
var num = parseInt(hex, 16);
var maxVal = Math.pow(2, hex.length / 2 * 8);
if (num > maxVal / 2 - 1) {
num = num - maxVal
}
return num;
}

View File

@ -0,0 +1,261 @@
/**
* @description
* @typedef {Object} VecRenderNumberVertices
* @property {number[]} lineVertices
* @property {number[]} maskVertices
*/
/**
* @description
* @typedef {Object} WaveValueFormatMaxMin
* @property {number} maxVal
* @property {number} minVal
*/
import { maskColorIndexOffset } from "../render-utils";
import { hexToSignedInt } from "./renderFormat";
function makeQuadVertices(p1, p2, p3, p4) {
return [
...p1, ...p2, ...p3,
...p1, ...p3, ...p4
]
}
/**
* @description Digital
* @param {GlobalLookup} lookup
* @param {string} link
* @param {(string | number)[]} wave
* @param {number} time
* @returns {VecRenderNumberVertices}
*/
export function renderAsCommonDigital(lookup, link, wave, time) {
const length = wave.length;
const lineVertices = [];
const maskVertices = [];
for (let i = 0; i < length; ++ i) {
const [t1, val, mask] = wave[i];
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
// t1(val) --- t2(val)
// 详见 设计图 ./design/webgl.drawio makeVecVertex原理 sheet
// 此处的 y 不是 y 的索引,详见 gl_Shifts_for_bar 的设计
const p0 = {x: t1, y: 0};
const p1 = {x: t2, y: 0};
const a0 = {x: t1, y: 4};
const a1 = {x: t2, y: 5};
const a2 = {x: t1, y: 1};
const a3 = {x: t2, y: 2};
let color = 5;
const renderOptions = lookup.currentSignalRenderOptions;
if (mask) {
color = 4;
} else if (renderOptions.has(link)) {
const option = renderOptions.get(link);
if (typeof option.color === 'number') {
color = option.color;
}
}
const points = [ a1, p1, a3, a2, p0, a0 ];
const wsIndice = [ 1, 2, 3, 5, 6, 7 ];
for (let j = 0; j < 6; ++ j) {
const prePoint = points[j];
const nextPoint = points[(j + 1) % 6];
const preWsIndex = wsIndice[j];
const nextWsIndex = wsIndice[(j + 1) % 6];
const quadVertices = makeQuadVertices(
[prePoint.x, prePoint.y, color, preWsIndex],
[prePoint.x, prePoint.y, color, (preWsIndex + 4) % 8],
[nextPoint.x, nextPoint.y, color, (nextWsIndex + 4) % 8],
[nextPoint.x, nextPoint.y, color, nextWsIndex],
);
lineVertices.push(...quadVertices);
}
const maskTriangles = [
[3, 4, 5],
[5, 0, 3],
[0, 3, 2],
[0, 1, 2]
];
for (const triangleIndice of maskTriangles) {
const [i1, i2, i3] = triangleIndice;
const point1 = points[i1];
const point2 = points[i2];
const point3 = points[i3];
maskVertices.push(
point1.x, point1.y, color + maskColorIndexOffset, wsIndice[i1],
point2.x, point2.y, color + maskColorIndexOffset, wsIndice[i2],
point3.x, point3.y, color + maskColorIndexOffset, wsIndice[i3]
);
}
}
return { lineVertices, maskVertices };
}
/**
*
* @param {GlobalLookup} lookup
* @param {string} link
*/
function getValFormatCode(lookup, link) {
const renderOptions = lookup.currentSignalRenderOptions;
if (renderOptions.has(link)) {
const option = renderOptions.get(link);
if (typeof option.valueFormat === 'number') {
return option.valueFormat;
} else {
return 0;
}
}
return 0;
}
/**
* @description 计算为 js 的数字如果当前模式为 有符号整型需要先转换成 有符号数进行比较
* @param {number} formatCode
* @param {number | string} val
* @param {number} width
*/
function explainAsJSNumber(formatCode, val, width) {
if (formatCode === 3) {
if (typeof val === 'number') {
val = val.toString(16);
}
if (val.startsWith('0x')) {
val = val.substring(2);
}
if (val.length < width) {
val = '0'.repeat(width - val.length) + val;
}
return hexToSignedInt(val);
} else {
return parseInt(val);
}
}
/**
* @description Analog (Ladder) 阶梯状
* @param {string} link
* @param {(string | number)[]} wave
* @param {number} time
* @param {number} formatCode
* @param {number} width
* @returns {WaveValueFormatMaxMin}
*/
function getMaxMinByFormat(link, wave, time, formatCode, width) {
let maxVal = undefined;
let minVal = undefined;
// TODO : 优化这段代码
for (let i = 0; i < wave.length; ++ i) {
const [t1, val, mask] = wave[i];
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
const numVal = explainAsJSNumber(formatCode, val, width);
if (maxVal === undefined) {
maxVal = numVal;
} else {
maxVal = Math.max(maxVal, numVal);
}
if (minVal === undefined) {
minVal = numVal;
} else {
minVal = Math.min(minVal, numVal);
}
}
return { maxVal, minVal };
}
/**
*
* @param {number} formatCode
* @param {number} maxVal
* @param {number} minVal
* @returns {(val: number) => number}
*/
function getMappingFunc(formatCode, maxVal, minVal) {
if (formatCode === 3) {
const maxAbs = Math.max(Math.abs(maxVal), Math.abs(minVal));
const k = 1 / maxAbs;
const b = -1;
// 把 [-maxAbs, +maxAbs] 映射到 [-1, 1]
return val => k * (val + maxAbs) + b;
} else {
const k = 2 / maxVal;
const b = -1;
// 把 [0, max] 映射到 [-1, 1]
return val => k * val + b;
}
}
/**
* @description Analog (Ladder) 阶梯状
* @param {GlobalLookup} lookup
* @param {string} link
* @param {(string | number)[]} wave
* @param {number} time
* @returns {VecRenderNumberVertices}
*/
export function renderAsLadderAnalog(lookup, link, wave, time) {
const renderOptions = lookup.currentSignalRenderOptions;
const formatCode = getValFormatCode(lookup, link);
const signal = lookup.link2CurrentWires.get(link);
const width = signal.size;
const { maxVal, minVal } = getMaxMinByFormat(lookup, link, wave, time, formatCode, width);
const coordinateTransform = getMappingFunc(formatCode, maxVal, minVal);
const length = wave.length;
const lineVertices = [];
const maskVertices = [];
for (let i = 0; i < length; ++ i) {
const [t1, val, mask] = wave[i];
const t2 = (i === (length - 1)) ? time : wave[i + 1][0];
let color = 5;
if (mask) {
color = 4;
} else if (renderOptions.has(link)) {
const option = renderOptions.get(link);
if (typeof option.color === 'number') {
color = option.color;
}
}
const numVal = explainAsJSNumber(formatCode, val, width);
const y = coordinateTransform(numVal);
}
}
/**
* @description Analog (Line) 模拟状
* @param {GlobalLookup} lookup
* @param {string} link
* @param {(string | number)[]} wave
* @param {number} time
* @returns {VecRenderNumberVertices}
*/
export function renderAsLineAnalog(lookup, link, wave, time) {
const renderOptions = lookup.currentSignalRenderOptions;
const formatCode = getValFormatCode(lookup, link);
const { maxVal, minVal } = getMaxMinByFormat(lookup, link, wave, time, formatCode);
}

View File

@ -89,6 +89,7 @@
* @property {WaveRenderSidebarItem[]} currentWiresRenderView
* @property {Record<string, BigInt | string>} currentSignalValues
* @property {Set<string>} sidebarSelectedWireLinks
* @property {Map<string, IRenderOption>} currentSignalRenderOptions
* @property {number} time
*/
@ -146,8 +147,8 @@
/**
* @typedef {Object} IRenderOption
* @property {number | undefined} height 波形的高度默认为 30可以在右侧的栏目中设置
* @property {string | undefined} color 波形的颜色可以在右击菜单栏中设置
* @property {number | undefined} valueFormat 波形数字的展示形式可以在上侧的下拉菜单中设置vec 类型的波形可以设置为0二进制1八进制2十六进制3有符号整型4无符号整型5浮点数半精度6单精度7双精度
* @property {number | undefined} color 波形的颜色可以在右击菜单栏中设置
* @property {number | undefined} valueFormat 波形数字的展示形式可以在上侧的下拉菜单中设置vec 类型的波形可以设置为0二进制1八进制2十六进制3有符号整型4无符号整型5浮点数半精度6单精度7双精度
* @property {number | undefined} renderModal 波形的渲染模式默认为 bit vecvec 类型的波形可以设置为0数字形式1折线模拟形式2阶梯模拟形式
*/

8320
yarn.lock

File diff suppressed because it is too large Load Diff