/
Team8
/
kittycad
Обзор
Документация
Войти
/
Team8
/
kittycad
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/graphics/rendering.cpp
401 строка
10 KB
levovix
add: prototype for Thread (резьба)
08 янв 2026, 21:35
08 янв 2026, 21:35
fcd7540
Код
Авторство
О чём код?
#include "rendering.h" #include <stdexcept> #include <string> #include <array> #include "mb_data.h" #include "mesh.h" #include "solid.h" #include <QtOpenGL/QOpenGLFunctions_3_3_Compatibility> QOpenGLFunctions_3_3_Compatibility gl_v; QOpenGLFunctions_3_3_Compatibility& gl{gl_v}; #define GL gl. void checkGlErrors() { GLenum errcode = glGetError(); if (errcode != 0) { throw std::runtime_error(std::string("opengl error code: ") + glErrorToString(errcode)); } } void setUniform(GLint handle, V4f const& v) { if (handle != -1) { GL glUniform4f(handle, v.x, v.y, v.z, v.w); } } void setUniform(GLint handle, V3f const& v) { if (handle != -1) { GL glUniform3f(handle, v.x, v.y, v.z); } } void setUniform(GLint handle, float v) { if (handle != -1) { GL glUniform1f(handle, v); } } void setUniform(GLint handle, int v) { if (handle != -1) { GL glUniform1i(handle, v); } } void setUniform(GLint handle, M4f const& v, bool transpose) { if (handle != -1) { GL glUniformMatrix4fv(handle, 1, transpose, v.c); } } void glfw_error_callback(int error, const char* description) { throw std::runtime_error(std::string("GLFW Error ") + std::to_string(error) + ": " + description); } char const* glErrorToString(int errcode) { switch(errcode) { case 0x0500: return "invalid enum"; case 0x0501: return "invalid value"; case 0x0502: return "invalid operation"; case 0x0503: return "stack overflow"; case 0x0504: return "stack underflow"; case 0x0505: return "out of memory"; case 0x0506: return "invalid framebuffer operation"; case 0x8031: return "table too large"; case 0: return "no error"; default: return "unknown error"; } } void raiseCompilationErrorsIfAny(GLuint handle, GLenum statusKind) { GLint success; if (statusKind == GL_COMPILE_STATUS) { GL glGetShaderiv(handle, statusKind, &success); } else { GL glGetProgramiv(handle, statusKind, &success); } if (success != GL_TRUE) { char buffer[512]; GLsizei len; GL glGetShaderInfoLog(handle, 512, &len, buffer); throw std::runtime_error(std::string("Failed to compile shader: ") + std::string(buffer, len)); } } // --- Shaders --- GLuint newShader(char const* vert, char const* frag, char const* version) { checkGlErrors(); GLuint vertHandle = GL glCreateShader(GL_VERTEX_SHADER); GLuint fragHandle = GL glCreateShader(GL_FRAGMENT_SHADER); char const* vertVersioned[] = {version, vert}; char const* fragVersioned[] = {version, frag}; GL glShaderSource(vertHandle, 2, vertVersioned, nullptr); GL glShaderSource(fragHandle, 2, fragVersioned, nullptr); GL glCompileShader(vertHandle); GL glCompileShader(fragHandle); raiseCompilationErrorsIfAny(vertHandle, GL_COMPILE_STATUS); raiseCompilationErrorsIfAny(fragHandle, GL_COMPILE_STATUS); GLuint program = GL glCreateProgram(); GL glAttachShader(program, vertHandle); GL glAttachShader(program, fragHandle); GL glLinkProgram(program); raiseCompilationErrorsIfAny(program, GL_LINK_STATUS); checkGlErrors(); return program; } void DrawContext::Shaders::Flat::use(Uniforms const& args) { checkGlErrors(); GL glUseProgram(handle); setUniform(model, args.model); setUniform(view, args.view); setUniform(projection, args.projection); setUniform(color, args.color); checkGlErrors(); } void DrawContext::Shaders::Shaded::use(Uniforms const& args) { checkGlErrors(); GL glUseProgram(handle); setUniform(model, args.model); setUniform(view, args.view); setUniform(projection, args.projection); setUniform(color, args.color); setUniform(shadowColor, args.shadowColor); setUniform(lightDir, v3f_sub({}, v3f_norm(args.lightDir, 1e-6, {}))); setUniform(backlight, args.backlight); checkGlErrors(); } void initShaders(DrawContext& ctx, char const* version) { #define UNIFORM(name) shader.name = GL glGetUniformLocation(shader.handle, #name); { auto& shader = ctx.shaders.flat; char const* vert = R"_( in vec3 inPos; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(inPos, 1.0); } )_"; char const* frag = R"_( uniform vec4 color; out vec4 fragColor; void main() { fragColor = color; } )_"; shader.handle = newShader(vert, frag, version); UNIFORM(color) UNIFORM(model) UNIFORM(view) UNIFORM(projection) } { auto& shader = ctx.shaders.shaded; char const* vert = R"_( in vec3 inPos; in vec3 inNormal; out vec4 lColor; uniform mat4 model; uniform mat4 view; uniform mat4 projection; uniform vec4 color; uniform vec4 shadowColor; uniform vec3 lightDir; uniform float backlight; void main() { gl_Position = projection * view * model * vec4(inPos, 1.0); vec3 normal = (model * vec4(inNormal, 1.0)).xyz; float lightV = dot(lightDir, (normal / length(normal)).xyz); float light = lightV > 0? lightV : -lightV * backlight; lColor = color * light + shadowColor * (1 - light); } )_"; char const* frag = R"_( out vec4 fragColor; in vec4 lColor; void main() { fragColor = lColor; } )_"; shader.handle = newShader(vert, frag, version); UNIFORM(model) UNIFORM(view) UNIFORM(projection) UNIFORM(color) UNIFORM(shadowColor) UNIFORM(lightDir) UNIFORM(backlight) } #undef UNIFORM } // --- Mesh --- owned<Mesh> newMesh(MeshData data) { assert(data.vertices != nullptr); if (data.normals != nullptr) { assert(data.vertexCount == data.normalCount); } if (data.surfaceIndices != nullptr) { assert(data.vertexCount == data.surfaceIndexCount); } checkGlErrors(); auto mesh = owned<Mesh>(new Mesh); mesh->kind = data.kind; mesh->elementCount = data.indices != nullptr ? data.indexCount : data.vertexCount; GL glGenVertexArrays(1, &mesh->vao); if (data.vertices != nullptr) { GL glGenBuffers(1, &mesh->vertices); } if (data.indices != nullptr) { GL glGenBuffers(1, &mesh->indices); } if (data.normals != nullptr) { GL glGenBuffers(1, &mesh->normals); } if (data.surfaceIndices != nullptr) { GL glGenBuffers(1, &mesh->surfaceIndices); } GL glBindVertexArray(mesh->vao); GL glBindBuffer(GL_ARRAY_BUFFER, mesh->vertices); GL glBufferData(GL_ARRAY_BUFFER, sizeof(Mesh::vertex_t) * data.vertexCount, data.vertices, data.usage); if (data.indices != nullptr) { GL glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->indices); GL glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Mesh::index_t) * data.indexCount, data.indices, data.usage); } GL glVertexAttribPointer( 0, sizeof(Mesh::vertex_t) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Mesh::vertex_t), nullptr ); GL glEnableVertexAttribArray(0); if (data.normals != nullptr) { GL glBindBuffer(GL_ARRAY_BUFFER, mesh->normals); GL glBufferData(GL_ARRAY_BUFFER, sizeof(Mesh::normal_t) * data.normalCount, data.normals, data.usage); GL glVertexAttribPointer( 1, sizeof(Mesh::normal_t) / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Mesh::normal_t), nullptr ); GL glEnableVertexAttribArray(1); } if (data.surfaceIndices != nullptr) { GL glBindBuffer(GL_ARRAY_BUFFER, mesh->surfaceIndices); GL glBufferData(GL_ARRAY_BUFFER, sizeof(Mesh::surfaceIndex_t) * data.surfaceIndexCount, data.surfaceIndices, data.usage); GL glVertexAttribIPointer( 2, 1, GL_INT, sizeof(Mesh::surfaceIndex_t), nullptr ); GL glEnableVertexAttribArray(2); } GL glBindVertexArray(0); checkGlErrors(); return mesh; } void draw(Mesh const& mesh) { checkGlErrors(); GL glBindVertexArray(mesh.vao); if (mesh.hasIndices()) { glDrawElements(mesh.kind, mesh.elementCount, GL_UNSIGNED_INT, nullptr); } else { glDrawArrays(mesh.kind, 0, mesh.elementCount); } GL glBindVertexArray(0); checkGlErrors(); } void initMeshes(DrawContext& ctx) { { std::array<Mesh::vertex_t, 4> vertices = { Mesh::vertex_t{-0.5, 0.5, 0}, Mesh::vertex_t{-0.5, -0.5, 0}, Mesh::vertex_t{0.5, 0.5, 0}, Mesh::vertex_t{0.5, -0.5, 0}, }; std::array<Mesh::index_t, 4> indices = { 0, 1, 2, 3 }; ctx.shapes.rect = newMesh({ .vertices = vertices.data(), .vertexCount = vertices.size(), .indices = indices.data(), .indexCount = indices.size(), .kind = GL_TRIANGLE_STRIP }); } } owned<Mesh> toMesh(MbSolid* solid) { if (solid == nullptr) { return nullptr; } MbStepData stepData; stepData.InitStepBySag(0.01); MbMesh mesh; solid->CalculateGrid(stepData, mesh); mesh.ConvertAllToTriangles(); std::vector<MbGrid const*> grids; mesh.GetGrids(grids); std::vector<Mesh::vertex_t> vertices; std::vector<Mesh::index_t> indices; std::vector<Mesh::normal_t> normals; std::vector<Mesh::surfaceIndex_t> surfaceIndices; int surface_index = 0; for (auto grid : grids) { int offset = vertices.size(); vertices.reserve(vertices.size() + grid->PointsCount()); normals.reserve(normals.size() + grid->PointsCount()); surfaceIndices.reserve(surfaceIndices.size() + grid->PointsCount()); for (int ptI = 0; ptI < grid->PointsCount(); ++ptI) { MbCartPoint3D pt; grid->GetPoint(ptI, pt); vertices.push_back({(GLfloat)pt.x, (GLfloat)pt.y, (GLfloat)pt.z}); MbVector3D nm; grid->GetNormal(ptI, nm); normals.push_back({(GLfloat)nm.x, (GLfloat)nm.y, (GLfloat)nm.z}); surfaceIndices.push_back(surface_index); } indices.reserve(indices.size() + grid->TrianglesCount() * 3); for (int triI = 0; triI < grid->TrianglesCount(); ++triI) { uint i0; uint i1; uint i2; grid->GetTrianglePointIndex(triI, i0, i1, i2); indices.push_back(offset + i0); indices.push_back(offset + i1); indices.push_back(offset + i2); } ++surface_index; } return newMesh({ .vertices = vertices.data(), .vertexCount = static_cast<GLsizei>(vertices.size()), .indices = indices.data(), .indexCount = static_cast<GLsizei>(indices.size()), .normals = normals.data(), .normalCount = static_cast<GLsizei>(normals.size()), .surfaceIndices = surfaceIndices.data(), .surfaceIndexCount = static_cast<GLsizei>(surfaceIndices.size()), .kind = GL_TRIANGLES, .usage = GL_DYNAMIC_DRAW }); } Mesh::~Mesh() { if (vao != 0) { GL glDeleteVertexArrays(1, &vao); } if (vertices != 0) { GL glDeleteBuffers(1, &vertices); } if (indices != 0) { GL glDeleteBuffers(1, &indices); } if (normals != 0) { GL glDeleteBuffers(1, &normals); } }