Initial commit after setting up Gitea. At this point a 3D Cube is using the mpu6050 data being converted by the stm32f446to quaternions to be moved. It works, bare minimum
This commit is contained in:
431
main.cpp
Normal file
431
main.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
#include <cstdint>
|
||||
#include <handleapi.h>
|
||||
#include <thread>
|
||||
#include <windows.h>
|
||||
#include "include/glad/glad.h"
|
||||
#include "include/glfw/glfw3.h"
|
||||
#include <iostream>
|
||||
#include "include/glm/gtc/quaternion.hpp"
|
||||
#include "include/imgui/imgui.h"
|
||||
#include "include/imgui/imgui_impl_glfw.h"
|
||||
#include "include/imgui/imgui_impl_opengl3.h"
|
||||
#include "serialcomm.hpp"
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include "visualization.hpp"
|
||||
#include <vector>
|
||||
#include "include/glm/glm.hpp"
|
||||
#include "include/glm/gtc/matrix_transform.hpp"
|
||||
#include "include/glm/gtc/type_ptr.hpp"
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "include/stb/stb_image.h"
|
||||
#include "include/glm/gtc/type_ptr.hpp"
|
||||
|
||||
|
||||
// global variables for the communication between threads (gui, serial)
|
||||
std::mutex g_mutex;
|
||||
Quaternion g_currQuat = {1.0f, 0.0f, 0.0f, 0.0f};
|
||||
std::vector<Quaternion> g_quadHistory;
|
||||
bool g_running = true;
|
||||
HANDLE g_serialHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
|
||||
// shader
|
||||
const char *vertexShaderSource = "#version 330 core\n"
|
||||
"layout (location = 0) in vec3 aPos;\n"
|
||||
"layout (location = 1) in vec2 aTexCoord;\n"
|
||||
"uniform mat4 transformMatrix;\n"
|
||||
|
||||
"uniform mat4 model;\n"
|
||||
"uniform mat4 view;\n"
|
||||
"uniform mat4 projection;\n"
|
||||
|
||||
"out vec2 TexCoord;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = projection * view * model *vec4(aPos, 1.0);\n"
|
||||
" TexCoord = aTexCoord;\n"
|
||||
"}\0";
|
||||
|
||||
const char *fragmentShaderSource = "#version 330 core\n"
|
||||
"out vec4 FragColor;\n"
|
||||
"in vec2 TexCoord;\n"
|
||||
"uniform sampler2D ourTexture;\n"
|
||||
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" FragColor = texture(ourTexture, TexCoord);\n"
|
||||
"}\0";
|
||||
|
||||
|
||||
// handle the serial communication wioth the stm32 in a separate thread
|
||||
void serialParserThread() {
|
||||
// define communication variables
|
||||
const char* portName = "COM3";
|
||||
DWORD baudRate = CBR_115200;
|
||||
char buffer[64];
|
||||
DWORD bytesRead;
|
||||
std::string incompleteDataBuffer;
|
||||
|
||||
// establish communication to stm32
|
||||
g_serialHandle = initSerialPort(portName, baudRate);
|
||||
if (g_serialHandle == INVALID_HANDLE_VALUE){
|
||||
g_running = false;
|
||||
std::cout << "Serial connection FAILED" << std::endl;
|
||||
return;
|
||||
} else {std::cout << "Serial connection succesfully established" << std::endl;}
|
||||
|
||||
// serial reading loop
|
||||
while (g_running) {
|
||||
if (readSerialData(g_serialHandle, buffer, sizeof(buffer), bytesRead)) {
|
||||
if (bytesRead > 0) {
|
||||
// add newly arrived data to buffer
|
||||
buffer[bytesRead] = '\0';
|
||||
incompleteDataBuffer += buffer;
|
||||
|
||||
// process any complete lines in the buffer
|
||||
size_t pos;
|
||||
while ((pos = incompleteDataBuffer.find('\n')) != std::string::npos) {
|
||||
// create substring of completed line and erase it from incompleteDataBuffer
|
||||
std::string completeLine = incompleteDataBuffer.substr(0, pos);
|
||||
incompleteDataBuffer.erase(0, pos + 1);
|
||||
|
||||
// now parse the quaternions from line
|
||||
Quaternion quat;
|
||||
if (parseQuaternion(completeLine, quat)) {
|
||||
// lock mutex while updating it
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
g_currQuat = quat;
|
||||
g_quadHistory.push_back(quat);
|
||||
if (g_quadHistory.size() > 200) {
|
||||
g_quadHistory.erase(g_quadHistory.begin());
|
||||
}
|
||||
|
||||
std::cout << "w: " << g_currQuat.w << "x: " << g_currQuat.x << "y: " << g_currQuat.y << "z: " << g_currQuat.z << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// close and exit the thread
|
||||
CloseHandle(g_serialHandle);
|
||||
std::cout << "Serial communicatin thread exiting" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int main() {
|
||||
// Locap copy of quaternion
|
||||
Quaternion lQuad;
|
||||
|
||||
// initialize main window
|
||||
GLFWwindow* window = initWindow();
|
||||
if (!window) {
|
||||
std::cerr << "Window initialization failed in mainthread" << std::endl;
|
||||
return 1;
|
||||
} else {std::cout << "Window initialization succesful in mainthread" << std::endl;}
|
||||
|
||||
// compile the shaders
|
||||
int success;
|
||||
char errorLog[512];
|
||||
unsigned int vertexShader;
|
||||
unsigned int fragmentShader;
|
||||
|
||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(vertexShader, 512, NULL, errorLog);
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << errorLog << std::endl;
|
||||
}
|
||||
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(fragmentShader, 512, NULL, errorLog);
|
||||
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << errorLog << std::endl;
|
||||
}
|
||||
|
||||
|
||||
// link the shaders
|
||||
unsigned int shaderProgramm = glCreateProgram();
|
||||
glAttachShader(shaderProgramm, vertexShader);
|
||||
glAttachShader(shaderProgramm, fragmentShader);
|
||||
glLinkProgram(shaderProgramm);
|
||||
glGetProgramiv(shaderProgramm, GL_LINK_STATUS, &success);
|
||||
if(!success) {
|
||||
glGetShaderInfoLog(shaderProgramm, 512, NULL, errorLog);
|
||||
std::cout << "ERROR::LINKING::SHADER::COMPILATION_FAILED\n" << errorLog << std::endl;
|
||||
}
|
||||
glUseProgram(shaderProgramm);
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
// texture stuff
|
||||
unsigned int texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
// texture wrapping and filtering
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
// now load and create the texture
|
||||
int imWidth, imHeigth, imNrChannels;
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
unsigned char *data = stbi_load("kekusmaximus.jpg", &imWidth, &imHeigth, &imNrChannels, 0);
|
||||
if (data) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imWidth, imHeigth, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
} else {
|
||||
std::cout << "Failed to load texture" << std::endl;
|
||||
}
|
||||
stbi_image_free(data);
|
||||
|
||||
// configure depth settings for 3D
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
// only screen coordinates between -1 and 1 are visible, (0, 0, 0) being display centerpoint
|
||||
float vertexData[] = {
|
||||
// Front face
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // 0
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // 1
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // 2
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // 3
|
||||
|
||||
// Back face
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // 4
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // 5
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // 6
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // 7
|
||||
|
||||
// Left face
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // 8
|
||||
-0.5f, -0.5f, 0.5f, 1.0f, 0.0f, // 9
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, // 10
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, // 11
|
||||
|
||||
// Right face
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, // 12
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // 13
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // 14
|
||||
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, // 15
|
||||
|
||||
// Bottom face
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, // 16
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, // 17
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 1.0f, // 18
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, // 19
|
||||
|
||||
// Top face
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, // 20
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, // 21
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f, // 22
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f // 23
|
||||
};
|
||||
|
||||
unsigned int vertexIndices[] = {
|
||||
// Front face
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Back face
|
||||
4, 5, 6, 6, 7, 4,
|
||||
// Left face
|
||||
8, 9, 10, 10, 11, 8,
|
||||
// Right face
|
||||
12, 13, 14, 14, 15, 12,
|
||||
// Bottom face
|
||||
16, 17, 18, 18, 19, 16,
|
||||
// Top face
|
||||
20, 21, 22, 22, 23, 20
|
||||
};
|
||||
|
||||
// create vertex/element buffer object VBO to store data on GPU
|
||||
unsigned int VBO, VAO, EBO;
|
||||
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
// bind vertex to VBO buffer
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
|
||||
|
||||
// bind indices to EBO buffer
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertexIndices), vertexIndices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// add texture coordinates
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
// setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableSetMousePos;
|
||||
|
||||
// setup platform/renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
|
||||
// Start serial parsing thread
|
||||
// pass the address of the code in memory so that thread can start its instance of the function
|
||||
std::thread parserThread(serialParserThread);
|
||||
|
||||
// set rendering state of window
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
|
||||
// glm quad to test purposes
|
||||
|
||||
|
||||
// main rendering loop for the ui
|
||||
while (g_running && !glfwWindowShouldClose(window)) {
|
||||
// process new events from window evevnt queue
|
||||
glfwPollEvents();
|
||||
// clear the color buffer == clear the screen / / GL_DEPTH_BUFFER_BIT would be for 3D rendering
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// activate and bind texture before draw
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glUseProgram(shaderProgramm);
|
||||
|
||||
// use the texture actually
|
||||
glUniform1i(glGetUniformLocation(shaderProgramm, "outTexture"), 0);
|
||||
|
||||
// create the transformations - TRS order (translate, rotate, scale) for proper transformation
|
||||
// create identity matrix
|
||||
glm::mat4 transformMatrix = glm::mat4(1.0f);
|
||||
transformMatrix = glm::translate(transformMatrix, glm::vec3(0.3f, 0.1f, 0.0f));
|
||||
transformMatrix = glm::rotate(transformMatrix, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
|
||||
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
glm::mat4 view = glm::mat4(1.0f);
|
||||
glm::mat4 projection = glm::mat4(1.0f);
|
||||
// apply MVP
|
||||
//model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f));
|
||||
|
||||
// this need to be deleted and redone
|
||||
glm::quat kekus_q(g_currQuat.w, g_currQuat.x, g_currQuat.y, g_currQuat.z);
|
||||
|
||||
|
||||
model = glm::mat4_cast(kekus_q);
|
||||
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));
|
||||
projection = glm::perspective(glm::radians(45.0f), (float)1280 / (float)720, 0.1f, 100.f);
|
||||
|
||||
|
||||
// get uniform matrix location and set matrix
|
||||
// unsigned int transformLoc = glGetUniformLocation(shaderProgramm, "transformMatrix");
|
||||
// glad_glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transformMatrix));
|
||||
unsigned int modelLoc = glGetUniformLocation(shaderProgramm, "model");
|
||||
unsigned int viewLoc = glGetUniformLocation(shaderProgramm, "view");
|
||||
unsigned int projLoc = glGetUniformLocation(shaderProgramm, "projection");
|
||||
//shaderProgramm.setMat4("projection", projection);
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
|
||||
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
|
||||
// OpenGL 3D Render
|
||||
glBindVertexArray(VAO);
|
||||
//glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
|
||||
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
|
||||
// start imgui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
|
||||
// accessing g_currQuat through the mutex protection
|
||||
// limited scope block just for the mutex operations
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(g_mutex);
|
||||
lQuad = g_currQuat;
|
||||
|
||||
static int frame_count = 0;
|
||||
if (frame_count++ % 60 == 0) {
|
||||
std::cout << "Rendering frame with quaternion: "
|
||||
<< "w: " << g_currQuat.w << " x: " << g_currQuat.x
|
||||
<< " y: " << g_currQuat.y << " z: " << g_currQuat.z << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
ImGui::Text("Hello Daddy, I'm here to serve");
|
||||
ImGui::Text("w: %.4f x: %.4f y: %.4f z: %.4f", lQuad.w, lQuad.x, lQuad.y, lQuad.z);
|
||||
|
||||
// create scrolling section for last 200 measurements
|
||||
ImGui::BeginChild("History", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
// loop through quadHistory vector and display each element as line
|
||||
for (uint32_t i = 0; i < g_quadHistory.size(); i++) {
|
||||
const Quaternion& q = g_quadHistory[i];
|
||||
ImGui::Text("w: %.4f x: %.4f y: %.4f z: %.4f", q.w, q.x, q.y, q.z);
|
||||
}
|
||||
// enable autoscroll to newest entry
|
||||
if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
// render the frame
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
// swap the buffers to display what was rendered
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
}
|
||||
|
||||
// set the parsing thread to exit and wait for it
|
||||
g_running = false;
|
||||
if (parserThread.joinable()) {
|
||||
parserThread.join();
|
||||
}
|
||||
|
||||
// clean up ImGui
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
// clean up OpenGL
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
glDeleteProgram(shaderProgramm);
|
||||
|
||||
// clean up the window
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user