diff --git a/.vscode/settings.json b/.vscode/settings.json index 0cc1beb..33e4ce2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -60,6 +60,7 @@ "array": "cpp", "deque": "cpp", "iterator": "cpp", - "stack": "cpp" + "stack": "cpp", + "random": "cpp" } } \ No newline at end of file diff --git a/img/init_dark.json b/img/init_dark.json index 89fe09d..b5a44a5 100644 --- a/img/init_dark.json +++ b/img/init_dark.json @@ -55,7 +55,40 @@ 1.0, 1.0, 0.0 - ] + ], + "wave3d" : + { + "begin" : + [ + 0.0, + 0.0, + 1.0 + ], + "end" : + [ + 1.0, + 0.0, + 0.0 + ], + "fourth" : + [ + 1.0, + 1.0, + 0.0 + ], + "second" : + [ + 0.0, + 1.0, + 1.0 + ], + "third" : + [ + 0.0, + 1.0, + 0.0 + ] + } }, "debug" : [ diff --git a/img/init_light.json b/img/init_light.json index 5970c92..8ccecc1 100644 --- a/img/init_light.json +++ b/img/init_light.json @@ -1,55 +1,90 @@ { - "color" : - { - "background" : - [ - 1.0, - 1.0, - 1.0 + "rate": 65, + "color": { + "background": [ + 0.9921, + 0.9647, + 0.8901 ], - "bordor" : - [ + "bordor": [ 0.1, 0.1, 0.1 ], - "grid" : - [ + "grid": [ 0.3, 0.3, 0.3 ], - "icon" : - [ - 0.6, - 0.6, - 0.6, - 1.0 - ], - "iconClick" : - [ + "icon": [ 1.0, 1.0, 1.0, 0.0 ], - "text" : - [ + "iconClick": [ + 0.6, + 0.6, + 0.6, + 1.0 + ], + "text": [ 0.1, 0.1, 0.1 ], - "trig" : - [ + "trig": [ 1.0, 0.0, 0.0 ], - "wave" : - [ - 0.95, - 0.65, - 0.136 - ] - } + "wave": [ + 0.1921, + 0.4196, + 0.8039 + ], + "wave3d" : + { + "begin" : + [ + 1.0, + 1.0, + 0.0 + ], + "second" : + [ + 0.0, + 1.0, + 0.0 + ], + "third" : + [ + 0.0, + 1.0, + 1.0 + ], + "fourth" : + [ + 0.0, + 0.0, + 1.0 + ], + "end" : + [ + 1.0, + 0.0, + 1.0 + ] + } + }, + "scroll": 1, + "auto": [ + 6, + 3 + ], + "debug": [ + 1200, + 200, + 6 + ] } \ No newline at end of file diff --git a/include/draw_background.h b/include/draw_background.h index 98d96c2..c5ef59e 100644 --- a/include/draw_background.h +++ b/include/draw_background.h @@ -26,7 +26,7 @@ class BackgroundRender Shader dashedShader; TextRenderer valueText; Texture2D iconTexture; - InputBox volBox, timeBox; + InputBox volBox, timeBox, gradeBox; BackgroundRender() {} void BackgroundRenderInit(float scrWidth, float scrHeight); void drawBackground(float xStep, float yScale, float offset, float trigLevel); @@ -35,6 +35,9 @@ class BackgroundRender bool ifTrig; bool ifOverSampling; bool ifTrigAverage; + bool ifThreeDim; + bool ifMultiColor; + int maxColorGrade; glm::vec3 borderColor; glm::vec3 gridColor; glm::vec3 trigLineColor; diff --git a/include/input_box.h b/include/input_box.h index f351a20..6cc7cc3 100644 --- a/include/input_box.h +++ b/include/input_box.h @@ -2,6 +2,7 @@ #define INPUT_BOX_H #include +#include #include #include #include @@ -20,7 +21,7 @@ class InputBox void InputBoxInit(); void setPosition(float scrW, float scrH, float posX, float posY, float posW, float posH); void RenderInputBox(); - void TypeInCharacter(char key); + void TypeIn(int key); float getInputValue(); void exitInputBox(); diff --git a/include/three_dim_wave_renderer.h b/include/three_dim_wave_renderer.h new file mode 100644 index 0000000..2de8142 --- /dev/null +++ b/include/three_dim_wave_renderer.h @@ -0,0 +1,34 @@ +#ifndef THREE_DIM_WAVE_RENDERER_H +#define THREE_DIM_WAVE_RENDERER_H + +#include +#include +#include +#include + +#include "shader.h" + +class ThreeDimWaveRenderer +{ +public: + Shader SingleColorWaveShader; + Shader MultiColorWaveShader; + ThreeDimWaveRenderer() {} + void WaveRenderInit(); + void SetWaveAttribute(GLuint viewSize, float dataMin, float dataMax); + void SetBackgroundColor(glm::vec3 backgroundColor); + void SetColorGrade(int maxColorGrade); + void SetColorAttribute(glm::vec3 beginColor, glm::vec3 endColor); + void SetColorAttribute(glm::vec3 beginColor, glm::vec3 secondColor, glm::vec3 thirdColor, + glm::vec3 fourthColor, glm::vec3 endColor); + void ResetWaveData(float *waveFormData, unsigned int size); + void RenderWave(glm::vec2 offset, float xStep, float yScale, bool ifMultiColor); + +private: + // Render state + GLuint VAO, VBO, EBO; + GLuint dataSize, viewSize; //横轴分viewSize格 + float dataMin, dataMax; +}; + +#endif \ No newline at end of file diff --git a/init.json b/init.json index 0b8ede6..8ccecc1 100644 --- a/init.json +++ b/init.json @@ -42,7 +42,40 @@ 0.1921, 0.4196, 0.8039 - ] + ], + "wave3d" : + { + "begin" : + [ + 1.0, + 1.0, + 0.0 + ], + "second" : + [ + 0.0, + 1.0, + 0.0 + ], + "third" : + [ + 0.0, + 1.0, + 1.0 + ], + "fourth" : + [ + 0.0, + 0.0, + 1.0 + ], + "end" : + [ + 1.0, + 0.0, + 1.0 + ] + } }, "scroll": 1, "auto": [ @@ -52,6 +85,6 @@ "debug": [ 1200, 200, - 60 + 6 ] } \ No newline at end of file diff --git a/oscilloscope.cpp b/oscilloscope.cpp index b12467d..d7578a6 100644 --- a/oscilloscope.cpp +++ b/oscilloscope.cpp @@ -7,11 +7,14 @@ #include "udp_upper.h" #include "wave_renderer.h" +#include "three_dim_wave_renderer.h" #include "draw_background.h" #include #include #include +#include #include +#include #define DEBUG 1 @@ -29,15 +32,16 @@ void drawWaveForm(); void waveParameter(); void waveAutoSet(); void dataProcessing(); -void waveOverSampling(); //前后overSamplingDigit个点做平均 -void dataTrig(); //平均模式触发 -void dataTrig_direct(); //单次触发 +void waveOverSampling(); //前后overSamplingDigit个点做平均 +void dataTrig(); //平均模式触发 +void dataTrig_direct(); //单次触发 +void threeDimWavaDataMapper(); //三维波形数据映射 UINT Receive_Data(LPVOID lpVoid); void threadRestart(); #define DATA_SIZE 262144 #define VIEW_DATA_SIZE 8192 -#define VIEWADLE_DATA_SIZE 600 +//#define VIEWADLE_DATA_SIZE 600 #define TIME_DIVS 12 int dataSize = DATA_SIZE; //实际使用数据量 float scrWidth = 1200; @@ -49,15 +53,20 @@ glm::vec2 offset(0.0f, 0.0f); //偏移,既图像拖动量; 横轴单位 glm::vec2 offsetState(-0.0f, 0.0f); //历史偏移状态记录 float scaleState = 1; //纵轴缩放,窗口显示10000/scaleState个mV float timeStep = 1; //横轴步长,1/TIME_DIVS个窗口内的时间(us) -int timeExponent = 0; -float realTimeSamplingRate = 50; //实时采样率,单位MHz -float samplingRate = realTimeSamplingRate; //转换后的采样率,单位MHz(points/us) -int overSamplingDigit = 1; // 过采样。1既没有过采样,16既4位过采样 +int timeExponent = 0; //使timeStep大于10^x的最大x值,暂时没用 +float realTimeSamplingRate = 50; //实时采样率,单位MHz +float samplingRate = 50; //转换后的采样率,单位MHz(points/us) +int overSamplingDigit = 1; // 过采样。1既没有过采样,16既4位过采样 float trigLevel = 0; float trigLevelState = 100; +bool waveTrig = false; bool trigAverage = false; //多次触发图像做平均 bool wavePause = false; -bool waveTrig = false; +bool threeDim = false; +bool multiColor = false; + +int maxColorGrade = 32; //最大颜色等级 + int autoPeriodNum = 3; int autoVoltageNum = 6; float scrollSensitivity = 1; @@ -68,8 +77,12 @@ unsigned threadNum = 0; GLFWwindow *window; BackgroundRender background; WaveRenderer wave; +ThreeDimWaveRenderer wave3d; + float waveFormData[VIEW_DATA_SIZE * 2]; float waveData[DATA_SIZE]; +unsigned char threeDimDataBase[1024][512]; +float threeDimWaveData[1024 * 512 * 3]; glm::vec3 backgroundColor(0.1f, 0.1f, 0.1f); glm::vec3 waveColor(1.0f, 1.0f, 0.0f); @@ -106,10 +119,20 @@ void drawWaveForm() #else threadRestart(); #endif - if (!wavePause) - wave.ResetWaveData(waveFormData, dataSize); - background.drawBackground(timeStep, scaleState, offsetState.y + offset.y, trigLevel + trigLevelState); //画网格 - wave.RenderWave(offsetState + offset, timeStep * samplingRate, scaleState, waveColor); //画波形 + if (threeDim) + { + if (!wavePause) + wave3d.ResetWaveData(threeDimWaveData, sizeof(threeDimWaveData)); + wave3d.RenderWave(offsetState + offset, timeStep * samplingRate, scaleState, multiColor); //画波形 + background.drawBackground(timeStep, scaleState, offsetState.y + offset.y, trigLevel + trigLevelState); //画网格 + } + else + { + if (!wavePause) + wave.ResetWaveData(waveFormData, dataSize); + background.drawBackground(timeStep, scaleState, offsetState.y + offset.y, trigLevel + trigLevelState); //画网格 + wave.RenderWave(offsetState + offset, timeStep * samplingRate, scaleState, waveColor); //画波形 + } } void windowInit() @@ -140,8 +163,19 @@ void windowInit() } wave.WaveRenderInit("shader/wave.vs", "shader/wave.fs"); wave.SetWaveAttribute(TIME_DIVS, -5000, 5000); + wave3d.WaveRenderInit(); + wave3d.SetWaveAttribute(TIME_DIVS, -5000, 5000); + wave3d.SetColorGrade(maxColorGrade); + wave3d.SetBackgroundColor(glm::vec3(0.0f, 0.0f, 0.0f)); + wave3d.SetColorAttribute(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f)); + wave3d.SetColorAttribute(glm::vec3(0.0f, 0.0f, 1.0f), + glm::vec3(0.0f, 1.0f, 1.0f), + glm::vec3(0.0f, 1.0f, 0.0f), + glm::vec3(1.0f, 1.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f)); background.BackgroundRenderInit(scrWidth, scrHeight); background.setSize(scrWidth, scrHeight, scrWidth * 0.1, scrHeight * 0.06, viewWidth, viewHeight); + background.maxColorGrade = maxColorGrade; } void configurationInit() { @@ -156,6 +190,7 @@ void configurationInit() const std::unique_ptr writer(writerBuilder.newStreamWriter()); Json::Value root; Json::Value color; + Json::Value wave_3d; for (int i = 0; i < 3; i++) { color["background"].append(0.1f); @@ -167,12 +202,28 @@ void configurationInit() } color["icon"].append(1.0f); color["iconClick"].append(0.0f); - color["wave"].append({1.0f}); + color["wave"].append(1.0f); color["wave"].append(1.0f); color["wave"].append(0.0f); color["trig"].append(0.9f); color["trig"].append(0.3f); color["trig"].append(0.1f); + wave_3d["begin"].append(0.0f); + wave_3d["begin"].append(0.0f); + wave_3d["begin"].append(1.0f); + wave_3d["second"].append(0.0f); + wave_3d["second"].append(1.0f); + wave_3d["second"].append(1.0f); + wave_3d["third"].append(0.0f); + wave_3d["third"].append(1.0f); + wave_3d["third"].append(0.0f); + wave_3d["fourth"].append(1.0f); + wave_3d["fourth"].append(1.0f); + wave_3d["fourth"].append(0.0f); + wave_3d["end"].append(1.0f); + wave_3d["end"].append(0.0f); + wave_3d["end"].append(0.0f); + color["wave3d"] = wave_3d; root["color"] = color; root["rate"] = realTimeSamplingRate; root["auto"].append(autoVoltageNum); @@ -206,15 +257,52 @@ void configurationInit() autoVoltageNum = root["auto"][0].asInt(); autoPeriodNum = root["auto"][1].asInt(); Json::Value color = root["color"]; - backgroundColor = glm::vec3(color["background"][0].asFloat(), color["background"][1].asFloat(), color["background"][2].asFloat()); - waveColor = glm::vec3(color["wave"][0].asFloat(), color["wave"][1].asFloat(), color["wave"][2].asFloat()); - iconColor = glm::vec4(color["icon"][0].asFloat(), color["icon"][1].asFloat(), color["icon"][2].asFloat(), color["icon"][3].asFloat()); - iconClickColor = glm::vec4(color["iconClick"][0].asFloat(), color["iconClick"][1].asFloat(), color["iconClick"][2].asFloat(), color["iconClick"][3].asFloat()); - background.borderColor = glm::vec3(color["bordor"][0].asFloat(), color["bordor"][1].asFloat(), color["bordor"][2].asFloat()); - background.gridColor = glm::vec3(color["grid"][0].asFloat(), color["grid"][1].asFloat(), color["grid"][2].asFloat()); - background.textColor = glm::vec3(color["text"][0].asFloat(), color["text"][1].asFloat(), color["text"][2].asFloat()); - background.trigLineColor = glm::vec3(color["trig"][0].asFloat(), color["trig"][1].asFloat(), color["trig"][2].asFloat()); + backgroundColor = glm::vec3( + color["background"][0].asFloat(), + color["background"][1].asFloat(), + color["background"][2].asFloat()); + waveColor = glm::vec3( + color["wave"][0].asFloat(), + color["wave"][1].asFloat(), + color["wave"][2].asFloat()); + iconColor = glm::vec4( + color["icon"][0].asFloat(), + color["icon"][1].asFloat(), + color["icon"][2].asFloat(), + color["icon"][3].asFloat()); + iconClickColor = glm::vec4( + color["iconClick"][0].asFloat(), + color["iconClick"][1].asFloat(), + color["iconClick"][2].asFloat(), + color["iconClick"][3].asFloat()); + background.borderColor = glm::vec3( + color["bordor"][0].asFloat(), + color["bordor"][1].asFloat(), + color["bordor"][2].asFloat()); + background.gridColor = glm::vec3( + color["grid"][0].asFloat(), + color["grid"][1].asFloat(), + color["grid"][2].asFloat()); + background.textColor = glm::vec3( + color["text"][0].asFloat(), + color["text"][1].asFloat(), + color["text"][2].asFloat()); + background.trigLineColor = glm::vec3( + color["trig"][0].asFloat(), + color["trig"][1].asFloat(), + color["trig"][2].asFloat()); background.iconTexture.color = iconColor; + Json::Value wave_3d = color["wave3d"]; + wave3d.SetBackgroundColor(backgroundColor); + wave3d.SetColorAttribute( + glm::vec3(wave_3d["begin"][0].asFloat(), wave_3d["begin"][1].asFloat(), wave_3d["begin"][2].asFloat()), + glm::vec3(wave_3d["end"][0].asFloat(), wave_3d["end"][1].asFloat(), wave_3d["end"][2].asFloat())); + wave3d.SetColorAttribute( + glm::vec3(wave_3d["begin"][0].asFloat(), wave_3d["begin"][1].asFloat(), wave_3d["begin"][2].asFloat()), + glm::vec3(wave_3d["second"][0].asFloat(), wave_3d["second"][1].asFloat(), wave_3d["second"][2].asFloat()), + glm::vec3(wave_3d["third"][0].asFloat(), wave_3d["third"][1].asFloat(), wave_3d["third"][2].asFloat()), + glm::vec3(wave_3d["fourth"][0].asFloat(), wave_3d["fourth"][1].asFloat(), wave_3d["fourth"][2].asFloat()), + glm::vec3(wave_3d["end"][0].asFloat(), wave_3d["end"][1].asFloat(), wave_3d["end"][2].asFloat())); ifs.close(); } @@ -241,9 +329,6 @@ void mouse_scroll_callback(GLFWwindow *window, double xoffset, double yoffset) timeStep *= pow(10, -scrollSensitivity * yoffset / 10); if (timeStep < 1 || timeStep >= 1000000) timeStep *= pow(10, scrollSensitivity * yoffset / 10); - timeExponent = 0; - for (int temp = timeStep; temp >= 10; timeExponent++) - temp /= 10; } } void mouse_press_callback(GLFWwindow *window, int button, int action, int mods) @@ -285,29 +370,54 @@ void mouse_press_callback(GLFWwindow *window, int button, int action, int mods) else overSamplingDigit = 1; } - if (posX > scrWidth * 0.92 && posX < scrWidth * 0.98 && posY > scrHeight * 0.32 && posY < scrHeight * 0.35) //触发是否平均 + if (posX > scrWidth * 0.92 && posX < scrWidth * 0.98 && posY > scrHeight * 0.32 && posY < scrHeight * 0.35) //触发是否平均模式 { trigAverage = !trigAverage; background.ifTrigAverage = trigAverage; } + if (posX > scrWidth * 0.82 && posX < scrWidth * 0.9 && posY > scrHeight * 0.36 && posY < scrHeight * 0.39) //是否三维映射 + { + threeDim = !threeDim; + background.ifThreeDim = threeDim; + } + if (posX > scrWidth * 0.82 && posX < scrWidth * 0.88 && posY > scrHeight * 0.41 && posY < scrHeight * 0.44) //单色系或多色系 + { + if (threeDim) + { + multiColor = !multiColor; + background.ifMultiColor = multiColor; + } + } + if (posX > scrWidth * 0.9 && posX < scrWidth * 0.95 && posY > scrHeight * 0.46 && posY < scrHeight * 0.5) //灰度等级输入 + { + if (threeDim) + { + background.gradeBox.ifInputBoxShow = true; + } + } + else + { + background.gradeBox.exitInputBox(); + } if (Rsquare < scrWidth * 0.06 * scrWidth * 0.06) { background.iconTexture.color = iconClickColor; waveAutoSet(); //左键点图标autoset } - if (posX > scrWidth * 0.18 && posX < scrWidth * 0.26 && posY > scrHeight * 0.95 && posY < scrHeight * 0.99) //电压参数输入 + if (posX > scrWidth * 0.18 && posX < scrWidth * 0.24 && posY > scrHeight * 0.95 && posY < scrHeight * 0.99) //电压参数输入 { background.volBox.ifInputBoxShow = true; - background.timeBox.exitInputBox(); } - else if (posX > scrWidth * 0.38 && posX < scrWidth * 0.44 && posY > scrHeight * 0.95 && posY < scrHeight * 0.99) //时基参数输入 + else { - background.timeBox.ifInputBoxShow = true; background.volBox.exitInputBox(); } + if (posX > scrWidth * 0.38 && posX < scrWidth * 0.44 && posY > scrHeight * 0.95 && posY < scrHeight * 0.99) //时基参数输入 + { + background.timeBox.ifInputBoxShow = true; + } else { - background.volBox.exitInputBox(); background.timeBox.exitInputBox(); } } @@ -350,9 +460,10 @@ void mouse_cursor_callback(GLFWwindow *window, double xpos, double ypos) } if (type == 0) { - if (waveTrig == 0) - offset.x = (xpos - firstX) / viewWidth * timeStep * samplingRate; + offset.x = (xpos - firstX) / viewWidth * timeStep * samplingRate; offset.y = (ypos - firstY) / viewHeight / scaleState; + if (waveTrig) + offset.x = 0; } if (type && waveTrig) trigLevel = -(ypos - firstY) * 10000 / viewHeight / scaleState; @@ -361,14 +472,12 @@ void key_callback(GLFWwindow *window, int key, int scancode, int action, int mod { if (action == GLFW_RELEASE) { - if (key == GLFW_KEY_ESCAPE) + background.volBox.TypeIn(key); + background.timeBox.TypeIn(key); + background.gradeBox.TypeIn(key); + if (key == GLFW_KEY_ENTER) { - background.volBox.exitInputBox(); - background.timeBox.exitInputBox(); - } - if (background.volBox.ifInputBoxShow) - { - if (key == GLFW_KEY_ENTER) + if (background.volBox.ifInputBoxShow) { scaleState = 1000.0f / background.volBox.getInputValue(); background.volBox.exitInputBox(); @@ -377,24 +486,17 @@ void key_callback(GLFWwindow *window, int key, int scancode, int action, int mod if (scaleState < 0.5) scaleState = 0.5; } - else if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) - { - background.volBox.TypeInCharacter(key); - } - } - if (background.timeBox.ifInputBoxShow) - { - if (key == GLFW_KEY_ENTER) + if (background.timeBox.ifInputBoxShow) { timeStep = background.timeBox.getInputValue(); background.timeBox.exitInputBox(); - timeExponent = 0; - for (int temp = timeStep; temp >= 10; timeExponent++) - temp /= 10; } - else if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) + if (background.gradeBox.ifInputBoxShow) { - background.timeBox.TypeInCharacter(key); + maxColorGrade = background.gradeBox.getInputValue(); + background.maxColorGrade = maxColorGrade; + wave3d.SetColorGrade(maxColorGrade); + background.gradeBox.exitInputBox(); } } } @@ -455,6 +557,7 @@ void waveParameter() break; } } + average = 0; for (int i = min_index; i < max_index; i++) average += waveFormData[2 * i + 1]; average = average / freq_points; @@ -487,9 +590,6 @@ void waveAutoSet() timeStep = autoPeriodNum * period / TIME_DIVS; if (timeStep == 0) timeStep = 100; - timeExponent = 0; - for (int temp = timeStep; temp >= 10; timeExponent++) - temp /= 10; offsetState.x = 0; } @@ -524,7 +624,8 @@ void dataTrig() } for (int i = VIEW_DATA_SIZE / 2; i < dataSize - VIEW_DATA_SIZE / 2; i++) { - if ((waveData[i] > level) && (waveData[i - 1] < level)) + if ((waveData[i + 2] > level) && (waveData[i + 1] > level) && (waveData[i] > level) && + (waveData[i - 1] < level) && (waveData[i - 2] < level) && (waveData[i - 3] < level)) { for (int j = 0; j < VIEW_DATA_SIZE; j++) //触发点在波形数据中间 { @@ -558,7 +659,8 @@ void dataTrig_direct() int trigNum = 0; for (int i = VIEW_DATA_SIZE / 2; i < dataSize - VIEW_DATA_SIZE / 2; i++) { - if ((waveData[i] > level) && (waveData[i - 1] < level)) + if ((waveData[i + 2] > level) && (waveData[i + 1] > level) && (waveData[i] > level) && + (waveData[i - 1] < level) && (waveData[i - 2] < level) && (waveData[i - 3] < level)) { for (int j = 0; j < VIEW_DATA_SIZE; j++) //触发点在波形数据中间 { @@ -581,58 +683,127 @@ void dataTrig_direct() return; } } -void dataProcessing() +void threeDimWavaDataMapper() { - waveOverSampling(); - if (waveTrig) + float level = trigLevelState + trigLevel; + // int preTrigDepth = TIME_DIVS / 2 * timeStep * samplingRate; //暂时没有用,预触发深度始终在中间 + int trigNum = 0; + memset(threeDimDataBase, 0, sizeof(threeDimDataBase)); + for (int i = 1024 / 2; i < dataSize - 1024 / 2; i++) { - if (timeExponent >= 1 && overSamplingDigit == 1) + if ((waveData[i + 2] > level) && (waveData[i + 1] > level) && (waveData[i] > level) && + (waveData[i - 1] < level) && (waveData[i - 2] < level) && (waveData[i - 3] < level)) { - dataSize /= 10; - samplingRate /= 10; - for (int i = 0; i < dataSize; i++) + for (int j = 0; j < 1024; j++) //触发点在波形数据中间 { - waveData[i] = waveData[10 * i]; + int yDim = (int)(waveData[i + j - 1024 / 2] / 5000 * 256 + 256); + yDim = (yDim > 511) ? 511 : ((yDim < 0) ? 0 : yDim); + if (threeDimDataBase[j][yDim] < 255) + threeDimDataBase[j][yDim]++; } + i += 1024; + trigNum++; } - if (trigAverage) - dataTrig(); - else - dataTrig_direct(); } - else + for (int i = 0; i < 1024; i++) + { + for (int j = 0; j < 512; j++) + { + threeDimWaveData[(i * 512 + j) * 3] = i; + threeDimWaveData[(i * 512 + j) * 3 + 1] = (j - 256) * 5000 / 256; + threeDimWaveData[(i * 512 + j) * 3 + 2] = threeDimDataBase[i][j]; + } + } + dataSize = 1024; +} +void dataProcessing() +{ + dataSize = DATA_SIZE; + samplingRate = realTimeSamplingRate; + timeExponent = 0; + for (int temp = timeStep; temp >= 10; timeExponent++) + temp /= 10; + + if (threeDim) { - if (timeExponent == 0) + waveTrig = true; + background.ifTrig = true; + for (int temp = timeStep, i = 0; temp >= 2 && i < 5; temp /= 2, i++) { - for (int i = 0; i < VIEW_DATA_SIZE; i++) + dataSize /= 2; + samplingRate /= 2; + for (int i = 0; i < dataSize; i++) { - waveFormData[2 * i] = (float)i; - waveFormData[2 * i + 1] = waveData[i]; + waveData[i] = waveData[2 * i]; } } - else if (timeExponent == 1) + threeDimWavaDataMapper(); + } + else + { + waveOverSampling(); + if (waveTrig) { - dataSize /= 10; - samplingRate /= 10; - for (int i = 0; i < VIEW_DATA_SIZE && i < dataSize; i++) + if (overSamplingDigit == 1) { - waveFormData[2 * i] = (float)i; - waveFormData[2 * i + 1] = waveData[10 * i]; + if (timeStep >= 8 && timeStep < 16) + { + dataSize /= 8; + samplingRate /= 8; + for (int i = 0; i < dataSize; i++) + { + waveData[i] = waveData[8 * i]; + } + } + else if (timeStep >= 16) + { + dataSize /= 16; + samplingRate /= 16; + for (int i = 0; i < dataSize; i++) + { + waveData[i] = waveData[16 * i]; + } + } } + if (trigAverage) + dataTrig(); + else + dataTrig_direct(); } else { - dataSize /= 100; - samplingRate /= 100; - for (int i = 0; i < VIEW_DATA_SIZE && i < dataSize; i++) + if (timeStep < 8) { - waveFormData[2 * i] = (float)i; - waveFormData[2 * i + 1] = waveData[100 * i]; + for (int i = 0; i < VIEW_DATA_SIZE; i++) + { + waveFormData[2 * i] = (float)i; + waveFormData[2 * i + 1] = waveData[i]; + } + } + else if (timeStep < 32) + { + dataSize /= 8; + samplingRate /= 8; + for (int i = 0; i < VIEW_DATA_SIZE && i < dataSize; i++) + { + waveFormData[2 * i] = (float)i; + waveFormData[2 * i + 1] = waveData[8 * i]; + } + } + else + { + dataSize /= 32; + samplingRate /= 32; + for (int i = 0; i < VIEW_DATA_SIZE && i < dataSize; i++) + { + waveFormData[2 * i] = (float)i; + waveFormData[2 * i + 1] = waveData[32 * i]; + } } } + dataSize = (dataSize < VIEW_DATA_SIZE) ? dataSize : VIEW_DATA_SIZE; + waveParameter(); } - dataSize = (dataSize < VIEW_DATA_SIZE) ? dataSize : VIEW_DATA_SIZE; - waveParameter(); } void threadRestart() @@ -659,7 +830,13 @@ void threadRestart() } } } - +double Gaussian_noise(double mean, double stddev) +{ + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine generator(seed); + std::normal_distribution dist(mean, stddev); + return dist(generator); +} #if DEBUG UINT Receive_Data(LPVOID lpVoid) { @@ -671,7 +848,10 @@ UINT Receive_Data(LPVOID lpVoid) float period = debugWavePeriod * realTimeSamplingRate; for (unsigned i = 0; i < DATA_SIZE; i++) { - waveData[i] = debugWaveRange / 2 * sin((float)i * 6.2832f / period + timeValue) + debugWaveOffset; + float noise = 1; + if (threeDim) + noise = Gaussian_noise(1, 0.2); + waveData[i] = noise * debugWaveRange / 2 * sin((float)i * 6.2832f / period + timeValue) + debugWaveOffset; } dataProcessing(); Sleep(500); diff --git a/oscilloscope.exe b/oscilloscope.exe index 65370e4..0122933 100644 Binary files a/oscilloscope.exe and b/oscilloscope.exe differ diff --git a/shader/colorfulwave.fs b/shader/colorfulwave.fs new file mode 100644 index 0000000..ccbed50 --- /dev/null +++ b/shader/colorfulwave.fs @@ -0,0 +1,50 @@ +#version 330 core +out vec4 FragColor; +in float colorGrade; + +uniform vec3 backgroundColor; +uniform vec3 beginColor; +uniform vec3 secondColor; +uniform vec3 thirdColor; +uniform vec3 fourthColor; +uniform vec3 endColor; +uniform int maxGrade; + +vec3 calculateColorFromGrade(float grade) +{ + vec3 stepColor; + vec3 resultColor; + int cgrade=int(grade); + int mgrade=maxGrade/4; + cgrade=(cgrade>maxGrade)?maxGrade:cgrade; + if(cgrademaxGrade)?maxGrade:cgrade; + if(cgrade==0) + { + return backgroundColor; + } + return beginColor+cgrade*stepColor; +} + +void main() +{ + FragColor=vec4(calculateColorFromGrade(colorGrade),1.f); +} \ No newline at end of file diff --git a/shader/colorwave.vs b/shader/colorwave.vs new file mode 100644 index 0000000..303300d --- /dev/null +++ b/shader/colorwave.vs @@ -0,0 +1,11 @@ +#version 330 core +layout(location=0)in vec3 aPos; + +uniform mat4 projection; +out float colorGrade; + +void main() +{ + gl_Position=projection*vec4(aPos.xy,0.f,1.f); + colorGrade=aPos.z; +} \ No newline at end of file diff --git a/source/draw_background.cpp b/source/draw_background.cpp index db3e784..0c37ec0 100644 --- a/source/draw_background.cpp +++ b/source/draw_background.cpp @@ -8,13 +8,14 @@ void BackgroundRender::BackgroundRenderInit(float scrWidth, float scrHeight) this->iconTexture.Generate("img/uestc_icon.png", GL_RGBA); this->volBox.InputBoxInit(); this->timeBox.InputBoxInit(); + this->gradeBox.InputBoxInit(); this->iconTexture.color = glm::vec4(0.8f, 0.8f, 0.8f, 1.0f); this->fontSize = (GLuint)(scrWidth / 240) * 4; this->valueFontPath = "fonts/ARLRDBD.TTF"; this->valueText.Load(valueFontPath, this->fontSize); this->valueText.LoadChinese((wchar_t *)L"攀登计划", "fonts/兰亭序书法字体.ttf", this->fontSize * 2); this->valueText.LoadChinese((wchar_t *)L"周碧松张震籍北", "fonts/FZKTK.TTF", this->fontSize); - this->valueText.LoadChinese((wchar_t *)L"普通平均过采样", "fonts/simsun.ttc", this->fontSize); + this->valueText.LoadChinese((wchar_t *)L"普通平均过采样三维模式单多色系灰度等级", "fonts/simsun.ttc", this->fontSize); this->borderColor = glm::vec3(0.9f, 0.9f, 0.9f); this->gridColor = glm::vec3(0.6f, 0.6f, 0.6f); this->trigLineColor = glm::vec3(0.9f, 0.3f, 0.1f); @@ -138,11 +139,12 @@ void BackgroundRender::setSize(float scrWidth, float scrHeight, float viewportX, this->valueText.ClearChinese(); this->valueText.LoadChinese((wchar_t *)L"攀登计划", "fonts/兰亭序书法字体.ttf", this->fontSize * 2); this->valueText.LoadChinese((wchar_t *)L"周碧松张震籍北", "fonts/FZKTK.TTF", this->fontSize); - this->valueText.LoadChinese((wchar_t *)L"普通平均过采样", "fonts/simsun.ttc", this->fontSize); + this->valueText.LoadChinese((wchar_t *)L"普通平均过采样三维模式单多色系灰度等级", "fonts/simsun.ttc", this->fontSize); this->iconTexture.SetProjection(scrWidth, scrHeight); this->iconTexture.SetPosition(scrWidth * 0.84f, scrHeight - scrWidth * 0.16f, scrWidth * 0.12f, scrWidth * 0.12f); this->volBox.setPosition(scrWidth, scrHeight, viewportX * 1.886, viewportY * 0.42 - this->fontSize / 2, this->fontSize * 2.4, this->fontSize); this->timeBox.setPosition(scrWidth, scrHeight, viewportX * 3.94, viewportY * 0.42 - this->fontSize / 2, this->fontSize * 1.8, this->fontSize); + this->gradeBox.setPosition(scrWidth, scrHeight, this->scrWidth * 0.907, this->scrHeight * 0.504, this->fontSize * 1.8 * 1.2, this->fontSize * 1.2); } void BackgroundRender::drawBackground(float xStep, float yScale, float offset, float trigLevel) { @@ -253,7 +255,7 @@ void BackgroundRender::drawBackground(float xStep, float yScale, float offset, f std::string value = this->volBox.valueString; if (value.length() >= 4) value = value.substr(value.length() - 4); - this->valueText.RenderText(value, this->viewportX * 1.916, this->viewportY * 0.5 - this->fontSize / 2, 0.9f, this->textColor); + this->valueText.RenderText(value, this->viewportX * 1.916, this->viewportY * 0.5 - this->fontSize / 2, 0.9f, glm::vec3(0.1f, 0.1f, 0.1f)); } if (this->timeBox.ifInputBoxShow == true) { @@ -261,19 +263,11 @@ void BackgroundRender::drawBackground(float xStep, float yScale, float offset, f std::string value = this->timeBox.valueString; if (value.length() >= 3) value = value.substr(value.length() - 3); - this->valueText.RenderText(value, this->viewportX * 3.96, this->viewportY * 0.5 - this->fontSize / 2, 0.9f, this->textColor); + this->valueText.RenderText(value, this->viewportX * 3.96, this->viewportY * 0.5 - this->fontSize / 2, 0.9f, glm::vec3(0.1f, 0.1f, 0.1f)); } float paraX = this->viewportX * 1.1 + this->viewportW; float paraY = this->viewportY * 9; float paraD = this->viewportY * 1; - for (int i = 0; i < 6; i++) - { - std::string valueString = std::to_string(this->measuredValue[i].value); - valueString.erase(valueString.find(".") + 4); //舍掉小数点后三位 - this->valueText.RenderText(this->measuredValue[i].name + ":", paraX, paraY - i * paraD, 1.0f, this->textColor); - this->valueText.RenderTextAlignRight(valueString, paraX * 1.195, paraY - i * paraD, 1.0f, this->textColor); - this->valueText.RenderText(this->measuredValue[i].unit, paraX * 1.2, paraY - i * paraD, 1.0f, this->textColor); - } this->valueText.RenderChinese((wchar_t *)L"攀", this->viewportX * 0.1, this->scrHeight * 0.9, 1.0f, this->textColor); this->valueText.RenderChinese((wchar_t *)L"登", this->viewportX * 0.1, this->scrHeight * 0.8, 1.0f, this->textColor); this->valueText.RenderChinese((wchar_t *)L"计", this->viewportX * 0.1, this->scrHeight * 0.7, 1.0f, this->textColor); @@ -285,20 +279,50 @@ void BackgroundRender::drawBackground(float xStep, float yScale, float offset, f this->valueText.RenderChinese((wchar_t *)L"周碧松", this->viewportX * 8.5, paraY - 7.5 * paraD, 1.0f, this->textColor); this->valueText.RenderChinese((wchar_t *)L"张震", this->viewportX * 8.5, paraY - 8.1 * paraD, 1.0f, this->textColor); this->valueText.RenderChinese((wchar_t *)L"籍北", this->viewportX * 8.5, paraY - 8.7 * paraD, 1.0f, this->textColor); - if (this->ifPause) - this->valueText.RenderText("pause", this->viewportX * 5, this->viewportY * 0.5 - this->fontSize / 2, 1.0f, this->textColor); - if (this->ifOverSampling) - this->valueText.RenderChinese((wchar_t *)L"过采样", this->scrWidth * 0.82, this->scrHeight * 0.66, 1.2f, this->textColor); + if (this->ifThreeDim) + { + this->valueText.RenderChinese((wchar_t *)L"三维模式", this->scrWidth * 0.82, this->scrHeight * 0.61, 1.2f, this->textColor); + if (this->ifMultiColor) + this->valueText.RenderChinese((wchar_t *)L"多色系", this->scrWidth * 0.82, this->scrHeight * 0.56, 1.2f, this->textColor); + else + this->valueText.RenderChinese((wchar_t *)L"单色系", this->scrWidth * 0.82, this->scrHeight * 0.56, 1.2f, this->textColor); + this->valueText.RenderChinese((wchar_t *)L"灰度等级", this->scrWidth * 0.82, this->scrHeight * 0.51, 1.2f, this->textColor); + this->valueText.RenderText(":" + std::to_string(this->maxColorGrade), this->scrWidth * 0.9, this->scrHeight * 0.51, 1.2f, this->textColor); + if (this->gradeBox.ifInputBoxShow == true) + { + this->gradeBox.RenderInputBox(); + std::string value = this->gradeBox.valueString; + if (value.length() >= 3) + value = value.substr(value.length() - 3); + this->valueText.RenderText(value, this->scrWidth * 0.908, this->scrHeight * 0.51, 1.2f, glm::vec3(0.1f, 0.1f, 0.1f)); + } + } else - this->valueText.RenderChinese((wchar_t *)L"过采样", this->scrWidth * 0.82, this->scrHeight * 0.66, 1.2f, glm::vec3(0.6f, 0.6f, 0.6f)); - if (this->ifTrig) { - if (this->ifTrigAverage) - this->valueText.RenderChinese((wchar_t *)L"平均", this->scrWidth * 0.92, this->scrHeight * 0.66, 1.2f, this->textColor); + this->valueText.RenderChinese((wchar_t *)L"三维模式", this->scrWidth * 0.82, this->scrHeight * 0.61, 1.2f, glm::vec3(0.6f, 0.6f, 0.6f)); + for (int i = 0; i < 6; i++) + { + std::string valueString = std::to_string(this->measuredValue[i].value); + valueString.erase(valueString.find(".") + 4); //舍掉小数点后三位 + this->valueText.RenderText(this->measuredValue[i].name + ":", paraX, paraY - i * paraD, 1.0f, this->textColor); + this->valueText.RenderTextAlignRight(valueString, paraX * 1.195, paraY - i * paraD, 1.0f, this->textColor); + this->valueText.RenderText(this->measuredValue[i].unit, paraX * 1.2, paraY - i * paraD, 1.0f, this->textColor); + } + if (this->ifOverSampling) + this->valueText.RenderChinese((wchar_t *)L"过采样", this->scrWidth * 0.82, this->scrHeight * 0.66, 1.2f, this->textColor); else - this->valueText.RenderChinese((wchar_t *)L"平均", this->scrWidth * 0.92, this->scrHeight * 0.66, 1.2f, glm::vec3(0.6f, 0.6f, 0.6f)); - this->valueText.RenderText("trigger", this->viewportX * 6, this->viewportY * 0.5 - this->fontSize / 2, 1.0f, this->textColor); + this->valueText.RenderChinese((wchar_t *)L"过采样", this->scrWidth * 0.82, this->scrHeight * 0.66, 1.2f, glm::vec3(0.6f, 0.6f, 0.6f)); + if (this->ifTrig) + { + if (this->ifTrigAverage) + this->valueText.RenderChinese((wchar_t *)L"平均", this->scrWidth * 0.92, this->scrHeight * 0.66, 1.2f, this->textColor); + else + this->valueText.RenderChinese((wchar_t *)L"平均", this->scrWidth * 0.92, this->scrHeight * 0.66, 1.2f, glm::vec3(0.6f, 0.6f, 0.6f)); + this->valueText.RenderText("trigger", this->viewportX * 6, this->viewportY * 0.5 - this->fontSize / 2, 1.0f, this->textColor); + } } + if (this->ifPause) + this->valueText.RenderText("pause", this->viewportX * 5, this->viewportY * 0.5 - this->fontSize / 2, 1.0f, this->textColor); glDisable(GL_BLEND); glViewport(this->viewportX, this->viewportY, this->viewportW, this->viewportH); glm::mat4 transform; diff --git a/source/input_box.cpp b/source/input_box.cpp index 9657e60..18e07c9 100644 --- a/source/input_box.cpp +++ b/source/input_box.cpp @@ -40,9 +40,23 @@ void InputBox::RenderInputBox() this->boxShader.SetMatrix4fv("projection", projection); glDrawArrays(GL_LINE_LOOP, 0, 4); } -void InputBox::TypeInCharacter(char key) +void InputBox::TypeIn(int key) { - this->valueString += key; + if (!this->ifInputBoxShow) + return; + if (key == GLFW_KEY_ESCAPE) + { + this->exitInputBox(); + } + else if (key == GLFW_KEY_BACKSPACE) + { + if (this->valueString.length() > 0) + this->valueString.erase(this->valueString.length() - 1); + } + else if (key >= GLFW_KEY_0 && key <= GLFW_KEY_9) + { + this->valueString += key; + } } float InputBox::getInputValue() { diff --git a/source/three_dim_wave_renderer.cpp b/source/three_dim_wave_renderer.cpp new file mode 100644 index 0000000..63cc967 --- /dev/null +++ b/source/three_dim_wave_renderer.cpp @@ -0,0 +1,103 @@ +#include + +#include "three_dim_wave_renderer.h" + +unsigned int indices[511 * 1023 * 6]; +void ThreeDimWaveRenderer::WaveRenderInit() +{ + // Load and configure shader + this->SingleColorWaveShader.Compile("shader/colorwave.vs", "shader/colorwave.fs"); + this->MultiColorWaveShader.Compile("shader/colorfulwave.vs", "shader/colorfulwave.fs"); + glGenVertexArrays(1, &this->VAO); + glGenBuffers(1, &this->VBO); + glGenBuffers(1, &this->EBO); + memset(indices, 0, sizeof(indices)); + for (int i = 0; i < 1023; i++) + { + for (int j = 0; j < 511; j++) + { + indices[6 * (511 * i + j)] = 512 * i + j; //左上 + indices[6 * (511 * i + j) + 1] = 512 * i + j + 1; //左下 + indices[6 * (511 * i + j) + 2] = 512 * i + j + 512; //右上 + indices[6 * (511 * i + j) + 3] = 512 * i + j + 1; //左下 + indices[6 * (511 * i + j) + 4] = 512 * i + j + 512; //右上 + indices[6 * (511 * i + j) + 5] = 512 * i + j + 513; //右下 + } + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); +} +void ThreeDimWaveRenderer::SetWaveAttribute(GLuint viewSize, float dataMin, float dataMax) +{ + this->viewSize = viewSize; + this->dataMin = dataMin; + this->dataMax = dataMax; +} +void ThreeDimWaveRenderer::SetColorGrade(int maxColorGrade) +{ + this->SingleColorWaveShader.Use(); + this->SingleColorWaveShader.SetInteger("maxGrade", maxColorGrade); + this->MultiColorWaveShader.Use(); + this->MultiColorWaveShader.SetInteger("maxGrade", maxColorGrade); +} +void ThreeDimWaveRenderer::SetBackgroundColor(glm::vec3 backgroundColor) +{ + this->SingleColorWaveShader.Use(); + this->SingleColorWaveShader.SetVector3f("backgroundColor", backgroundColor); + this->MultiColorWaveShader.Use(); + this->MultiColorWaveShader.SetVector3f("backgroundColor", backgroundColor); +} +void ThreeDimWaveRenderer::SetColorAttribute(glm::vec3 beginColor, glm::vec3 endColor) +{ + this->SingleColorWaveShader.Use(); + this->SingleColorWaveShader.SetVector3f("beginColor", beginColor); + this->SingleColorWaveShader.SetVector3f("endColor", endColor); +} +void ThreeDimWaveRenderer::SetColorAttribute(glm::vec3 beginColor, glm::vec3 secondColor, glm::vec3 thirdColor, + glm::vec3 fourthColor, glm::vec3 endColor) +{ + this->MultiColorWaveShader.Use(); + this->MultiColorWaveShader.SetVector3f("beginColor", beginColor); + this->MultiColorWaveShader.SetVector3f("secondColor", secondColor); + this->MultiColorWaveShader.SetVector3f("thirdColor", thirdColor); + this->MultiColorWaveShader.SetVector3f("fourthColor", fourthColor); + this->MultiColorWaveShader.SetVector3f("endColor", endColor); +} +void ThreeDimWaveRenderer::ResetWaveData(float *waveFormData, unsigned int size) +{ + this->dataSize = 1024; + glBindVertexArray(this->VAO); + glBindBuffer(GL_ARRAY_BUFFER, this->VBO); + glBufferData(GL_ARRAY_BUFFER, size, waveFormData, GL_STREAM_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0); + + glEnableVertexAttribArray(0); +} +void ThreeDimWaveRenderer::RenderWave(glm::vec2 offset, float xStep, float yScale, bool ifMultiColor) +{ + float start = -(offset.x + xStep / 2) * this->viewSize + this->dataSize / 2; //缩放时中间不动,初始展示波形中间数据 + float end = start + this->viewSize * xStep; + float range = this->dataMax - this->dataMin; + float min = this->dataMin / yScale + offset.y * range; + float max = this->dataMax / yScale + offset.y * range; + glm::mat4 projection = glm::ortho(start, end, min, max); + if (start < 0) + start = 0; + if (end > this->dataSize) + end = this->dataSize; + if (ifMultiColor) + { + this->MultiColorWaveShader.Use(); + this->MultiColorWaveShader.SetMatrix4fv("projection", projection); + } + else + { + this->SingleColorWaveShader.Use(); + this->SingleColorWaveShader.SetMatrix4fv("projection", projection); + } + glBindVertexArray(this->VAO); + // glDrawArrays(GL_POINTS, 0, 1024 * 512); + glDrawElements(GL_TRIANGLES, 6 * 511 * 1023, GL_UNSIGNED_INT, 0); +} diff --git a/source/wave_renderer.cpp b/source/wave_renderer.cpp index ce7e642..15046ef 100644 --- a/source/wave_renderer.cpp +++ b/source/wave_renderer.cpp @@ -24,7 +24,7 @@ void WaveRenderer::ResetWaveData(float *waveFormData, unsigned int size) this->dataSize = size; glBindVertexArray(this->VAO); glBindBuffer(GL_ARRAY_BUFFER, this->VBO); - glBufferData(GL_ARRAY_BUFFER, size * 8, waveFormData, GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, size * 2 * sizeof(float), waveFormData, GL_STREAM_DRAW); // position attribute glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); diff --git "a/\345\220\257\345\212\250.bat" "b/\345\220\257\345\212\250.bat" new file mode 100644 index 0000000..a65ff9b --- /dev/null +++ "b/\345\220\257\345\212\250.bat" @@ -0,0 +1,25 @@ +@ECHO OFF&PUSHD %~DP0 &TITLE ѡģʽ +mode con cols=36 lines=20 +color E0 +cls + +echo. +echo ĸģʽ +echo ============================== +echo. +echo 1ɫģʽ +echo. +echo 2ɫģʽ +echo. +echo ============================== +echo. +echo. +set /p user_input=֣ +if %user_input% equ 1 ( + copy img\init_light.json init.json +) +if %user_input% equ 2 ( + copy img\init_dark.json init.json +) + +start oscilloscope.exe