From 1155067b2632f83a2aa7a52f7ae313ff1c81429a Mon Sep 17 00:00:00 2001 From: Ilusha Date: Sun, 17 Mar 2024 21:44:19 +0300 Subject: [PATCH] A little clean up --- Graphics/private/bindings/Canvas.cpp | 117 ----------- Graphics/public/Graphics.hpp | 3 - Math/private/Camera.cpp | 4 +- Math/public/Camera.hpp | 4 +- Sketch3D/applications/Entry.cpp | 4 +- Sketch3D/private/Sketch3D.cpp | 177 +++++++++++------ Sketch3D/public/Sketch3D.hpp | 283 ++++++++++----------------- Sketch3D/public/Sketch3DWidget.hpp | 49 +---- 8 files changed, 234 insertions(+), 407 deletions(-) diff --git a/Graphics/private/bindings/Canvas.cpp b/Graphics/private/bindings/Canvas.cpp index 946407d..a46c977 100644 --- a/Graphics/private/bindings/Canvas.cpp +++ b/Graphics/private/bindings/Canvas.cpp @@ -112,123 +112,6 @@ void Graphics::Canvas::text( popClamp(); } -void Graphics::Canvas::drawColorwheel(const RectF& rec, const RGB& col) { - - float const x = rec.x; - float const y = rec.y; - float const w = rec.z; - float const h = rec.w; - - HSV hsv = tp::HSV(col); - float const hue = hsv.h / (NVG_PI * 2); - - int i; - float r0, r1, ax, ay, bx, by, cx, cy, aeps, r; - NVGpaint paint; - - nvgSave(mContext->vg); - - cx = x + w * 0.5f; - cy = y + h * 0.5f; - r1 = (w < h ? w : h) * 0.5f - 5.0f; - r0 = r1 - 13.0f; - aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out). - - for (i = 0; i < 6; i++) { - float a0 = (float) i / 6.0f * NVG_PI * 2.0f - aeps; - float a1 = (float) (i + 1.0f) / 6.0f * NVG_PI * 2.0f + aeps; - nvgBeginPath(mContext->vg); - nvgArc(mContext->vg, cx, cy, r0, a0, a1, NVG_CW); - nvgArc(mContext->vg, cx, cy, r1, a1, a0, NVG_CCW); - nvgClosePath(mContext->vg); - ax = cx + cosf(a0) * (r0 + r1) * 0.5f; - ay = cy + sinf(a0) * (r0 + r1) * 0.5f; - bx = cx + cosf(a1) * (r0 + r1) * 0.5f; - by = cy + sinf(a1) * (r0 + r1) * 0.5f; - paint = nvgLinearGradient( - mContext->vg, - ax, - ay, - bx, - by, - nvgHSLA(a0 / (NVG_PI * 2), 1.0f, 0.55f, 255), - nvgHSLA(a1 / (NVG_PI * 2), 1.0f, 0.55f, 255) - ); - nvgFillPaint(mContext->vg, paint); - nvgFill(mContext->vg); - } - - nvgBeginPath(mContext->vg); - nvgCircle(mContext->vg, cx, cy, r0 - 0.5f); - nvgCircle(mContext->vg, cx, cy, r1 + 0.5f); - nvgStrokeColor(mContext->vg, nvgRGBA(0, 0, 0, 64)); - nvgStrokeWidth(mContext->vg, 1.0f); - nvgStroke(mContext->vg); - - // Selector - nvgSave(mContext->vg); - nvgTranslate(mContext->vg, cx, cy); - nvgRotate(mContext->vg, hue * NVG_PI * 2); - - // Marker on - nvgStrokeWidth(mContext->vg, 2.0f); - nvgBeginPath(mContext->vg); - nvgRect(mContext->vg, r0 - 1, -3, r1 - r0 + 2, 6); - nvgStrokeColor(mContext->vg, nvgRGBA(255, 255, 255, 192)); - nvgStroke(mContext->vg); - - paint = nvgBoxGradient(mContext->vg, r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, nvgRGBA(0, 0, 0, 128), nvgRGBA(0, 0, 0, 0)); - nvgBeginPath(mContext->vg); - nvgRect(mContext->vg, r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20); - nvgRect(mContext->vg, r0 - 2, -4, r1 - r0 + 4, 8); - nvgPathWinding(mContext->vg, NVG_HOLE); - nvgFillPaint(mContext->vg, paint); - nvgFill(mContext->vg); - - // Center triangle - r = r0 - 6; - ax = cosf(120.0f / 180.0f * NVG_PI) * r; - ay = sinf(120.0f / 180.0f * NVG_PI) * r; - bx = cosf(-120.0f / 180.0f * NVG_PI) * r; - by = sinf(-120.0f / 180.0f * NVG_PI) * r; - nvgBeginPath(mContext->vg); - nvgMoveTo(mContext->vg, r, 0); - nvgLineTo(mContext->vg, ax, ay); - nvgLineTo(mContext->vg, bx, by); - nvgClosePath(mContext->vg); - paint = nvgLinearGradient(mContext->vg, r, 0, ax, ay, nvgHSLA(hue, 1.0f, 0.5f, 255), nvgRGBA(255, 255, 255, 255)); - nvgFillPaint(mContext->vg, paint); - nvgFill(mContext->vg); - paint = nvgLinearGradient(mContext->vg, (r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, nvgRGBA(0, 0, 0, 0), nvgRGBA(0, 0, 0, 255)); - nvgFillPaint(mContext->vg, paint); - nvgFill(mContext->vg); - nvgStrokeColor(mContext->vg, nvgRGBA(0, 0, 0, 64)); - nvgStroke(mContext->vg); - - // Select circle on triangle - float yt = hsv.v * hsv.s; - float xt = hsv.v - 0.5 * yt; - ay = sinf(120.0f / 180.0f * NVG_PI) * r * (-1.0f + xt * 2.0f); - ax = cosf(120.0f / 180.0f * NVG_PI) * r * (1.0f - yt * 3.f); - nvgStrokeWidth(mContext->vg, 2.0f); - nvgBeginPath(mContext->vg); - nvgCircle(mContext->vg, ax, ay, 5); - nvgStrokeColor(mContext->vg, nvgRGBA(255, 255, 255, 192)); - nvgStroke(mContext->vg); - - paint = nvgRadialGradient(mContext->vg, ax, ay, 7, 9, nvgRGBA(0, 0, 0, 64), nvgRGBA(0, 0, 0, 0)); - nvgBeginPath(mContext->vg); - nvgRect(mContext->vg, ax - 20, ay - 20, 40, 40); - nvgCircle(mContext->vg, ax, ay, 7); - nvgPathWinding(mContext->vg, NVG_HOLE); - nvgFillPaint(mContext->vg, paint); - nvgFill(mContext->vg); - - nvgRestore(mContext->vg); - - nvgRestore(mContext->vg); -} - void Graphics::Canvas::drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding) { auto imgPaint = nvgImagePattern(mContext->vg, rec.x, rec.y, rec.z, rec.w, angle, image->id, alpha); nvgBeginPath(mContext->vg); diff --git a/Graphics/public/Graphics.hpp b/Graphics/public/Graphics.hpp index c9e0bc0..148eec5 100644 --- a/Graphics/public/Graphics.hpp +++ b/Graphics/public/Graphics.hpp @@ -91,12 +91,9 @@ namespace tp { void rect(const RectF& rec, const RGBA& col, halnf round = 0); void text(const char*, const RectF&, halnf size, Align, halnf marging, const RGBA&); - void drawColorwheel(const RectF& rec, const RGB& col); - ImageHandle createImageFromTextId(ualni id, Vec2F size); void deleteImageHandle(ImageHandle image); void drawImage(const RectF& rec, ImageHandle* image, halnf angle, halnf alpha, halnf rounding); - // TODO : API private: halnf mWidth = 600; diff --git a/Math/private/Camera.cpp b/Math/private/Camera.cpp index 546705d..f1cc43e 100644 --- a/Math/private/Camera.cpp +++ b/Math/private/Camera.cpp @@ -28,9 +28,9 @@ void Camera::setFar(halnf in) { mFar = in; } halnf Camera::getFOV() const { return mFOV; } -Mat4F Camera::calculateTransformationMatrix() { return calculateProjectionMatrix() * calculateViewMatrix(); } +Mat4F Camera::calculateTransformationMatrix() const { return calculateProjectionMatrix() * calculateViewMatrix(); } -Mat4F Camera::calculateViewMatrix() { +Mat4F Camera::calculateViewMatrix() const { const Vec3F& F = (mPos - mTarget).unitV(); const Vec3F& S = mUp * F; const Vec3F& U = F * S; diff --git a/Math/public/Camera.hpp b/Math/public/Camera.hpp index 4096f81..11f4b73 100644 --- a/Math/public/Camera.hpp +++ b/Math/public/Camera.hpp @@ -36,9 +36,9 @@ namespace tp { void offset_target(halnf val); public: - [[nodiscard]] Mat4F calculateTransformationMatrix(); + [[nodiscard]] Mat4F calculateTransformationMatrix() const; [[nodiscard]] Mat calculateProjectionMatrix() const; - [[nodiscard]] Mat calculateViewMatrix(); + [[nodiscard]] Mat calculateViewMatrix() const; [[nodiscard]] Vec3F project(Vec2F normalized); [[nodiscard]] Vec2F project(const Vec3F& world); [[nodiscard]] static Vec2F project(const tp::Vec3F& world, const tp::Mat4F& viewMat, const tp::Mat4F& projMat); diff --git a/Sketch3D/applications/Entry.cpp b/Sketch3D/applications/Entry.cpp index 849fbd0..5e22f67 100644 --- a/Sketch3D/applications/Entry.cpp +++ b/Sketch3D/applications/Entry.cpp @@ -13,7 +13,7 @@ void runApp() { auto window = tp::Window::createWindow(800, 600, "Window 1"); { - tp::Sketch3DWidget gui(window->getCanvas(), {800, 1000}); + tp::Sketch3DWidget gui(window->getCanvas(), {1800, 1000}); if (window) { while (!window->shouldClose()) { @@ -24,7 +24,7 @@ void runApp() { gui.proc(window->getEvents(), { area.x, area.y, area.z, area.w }, { area.x, area.y, area.z, area.w }); gui.draw(window->getCanvas()); - tp::sleep(100); + tp::sleep(10); window->draw(); } diff --git a/Sketch3D/private/Sketch3D.cpp b/Sketch3D/private/Sketch3D.cpp index 79de83f..3ca58a8 100644 --- a/Sketch3D/private/Sketch3D.cpp +++ b/Sketch3D/private/Sketch3D.cpp @@ -3,72 +3,74 @@ using namespace tp; -Stroke::GLHandles::GLHandles() { +StrokeGPUHandles::StrokeGPUHandles() { glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); glGenBuffers(1, &vertexbuffer); } -void Stroke::GLHandles::sendDataToGPU(tp::Buffer* mPoints) { +void StrokeGPUHandles::sendDataToGPU(Buffer* mPoints) { glBindVertexArray(VertexArrayID); vbo_len = mPoints->size(); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(mPoints[0]) * vbo_len, mPoints->getBuff(), GL_STATIC_DRAW); } -Stroke::GLHandles::~GLHandles() { +StrokeGPUHandles::~StrokeGPUHandles() { glDeleteBuffers(1, &vertexbuffer); glDeleteVertexArrays(1, &VertexArrayID); } -Stroke::Stroke() {} +Stroke::Stroke() = default; -tp::Buffer& Stroke::buff() { - return mPoints; -} +Buffer& Stroke::getPoints() { return mPoints; } -void Stroke::updateGpuBuffers() { - mGl.sendDataToGPU(&mPoints); -} +const Buffer& Stroke::getPoints() const { return mPoints; } -void Stroke::denoisePos(tp::halni passes) { - for (auto pass : tp::Range(passes)) { - for (auto pi : tp::Range(mPoints.size() - 2)) { +void Stroke::setColor(const RGBA& col) { mColor = col; } + +const RGBA& Stroke::getColor() const { return mColor; } + +void Stroke::updateGpuBuffers() { mGPUHandles.sendDataToGPU(&mPoints); } + +void Stroke::denoisePos(halni passes) { + for (auto pass : Range(passes)) { + for (auto pi : Range(mPoints.size() - 2)) { mPoints[pi + 1].pos = (mPoints[pi + 1].pos + mPoints[pi].pos + mPoints[pi + 2].pos) / 3.f; } } } -void Stroke::denoiseThickness(tp::halni passes) { - for (auto pass : tp::Range(passes)) { - for (auto pi : tp::Range(mPoints.size() - 2)) { +void Stroke::denoiseThickness(halni passes) { + for (auto pass : Range(passes)) { + for (auto pi : Range(mPoints.size() - 2)) { mPoints[pi + 1].thickness = (mPoints[pi].thickness + mPoints[pi + 2].thickness) / 2.f; } } } -void Stroke::compress(tp::halnf factor) { +void Stroke::compress(halnf factor) { if (mPoints.size() < 3) { return; } - tp::List passed_poits; + List passed_poits; - for (auto idx : tp::Range(mPoints.size())) { + for (auto idx : Range(mPoints.size())) { passed_poits.pushBack(mPoints[idx]); } - tp::List::Node* min_node = NULL; + List::Node* min_node = NULL; do { min_node = NULL; - tp::halnf min_factor = factor; + halnf min_factor = factor; - tp::List::Node* iter = passed_poits.first()->next; + List::Node* iter = passed_poits.first()->next; for (; iter->next; iter = iter->next) { - tp::Vec3F dir1 = (iter->data.pos - iter->prev->data.pos).normalize(); - tp::Vec3F dir2 = (iter->next->data.pos - iter->data.pos).normalize(); - tp::halnf factor = 1 - dir1.dot(dir2); + Vec3F dir1 = (iter->data.pos - iter->prev->data.pos).normalize(); + Vec3F dir2 = (iter->next->data.pos - iter->data.pos).normalize(); + halnf factor = 1 - dir1.dot(dir2); if (factor < min_factor) { min_node = iter; @@ -83,29 +85,30 @@ void Stroke::compress(tp::halnf factor) { mPoints.reserve(passed_poits.length()); - tp::ualni idx = 0; + + ualni idx = 0; for (auto point : passed_poits) { mPoints[idx] = point.data(); idx++; } } -void Stroke::subdiv(tp::halnf precision, tp::Camera* cam, tp::halni passes) { +void Stroke::subdiv(halnf precision, const Camera* cam, halni passes) { // TODO if (mPoints.size() < 4) { return; } - tp::List new_points; - for (auto idx : tp::Range(mPoints.size())) { + List new_points; + for (auto idx : Range(mPoints.size())) { new_points.pushBack(mPoints[idx]); } auto viewmat = cam->calculateViewMatrix(); auto projmat = cam->calculateProjectionMatrix(); - for (auto i : tp::Range(passes)) { + for (auto i : Range(passes)) { auto n_points = new_points.length(); @@ -129,9 +132,9 @@ void Stroke::subdiv(tp::halnf precision, tp::Camera* cam, tp::halni passes) { auto const ab = a.dot(b); auto const la = l.dot(a); auto const lb = l.dot(b); - tp::Vec3F mid; + Vec3F mid; - if (1 - tp::abs(ab) < 0.001f) { + if (1 - abs(ab) < 0.001f) { goto SKIP; } @@ -189,7 +192,7 @@ void Stroke::subdiv(tp::halnf precision, tp::Camera* cam, tp::halni passes) { if (new_points.length() != mPoints.size()) { mPoints.reserve(new_points.length()); - tp::ualni idx = 0; + ualni idx = 0; for (auto point : new_points) { mPoints[idx] = point.data(); idx++; @@ -201,11 +204,11 @@ PencilBrush::PencilBrush() { mType = "pencil"; } -void PencilBrush::unsureReady(Stroke* stroke, tp::Camera* cam, bool debug) { - if (stroke->buff().size() == 1) { - auto new_point = stroke->buff()[0]; +void PencilBrush::ensureReady(Stroke* stroke, const Camera* cam, bool debug) const { + if (stroke->getPoints().size() == 1) { + auto new_point = stroke->getPoints()[0]; new_point.pos += 0.00001f; - stroke->buff().append(new_point); + stroke->getPoints().append(new_point); } if (mEnableCompression && !debug) { @@ -217,24 +220,24 @@ void PencilBrush::unsureReady(Stroke* stroke, tp::Camera* cam, bool debug) { stroke->updateGpuBuffers(); } -void PencilBrush::sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) { +void PencilBrush::sample(Project* proj, Vec2F crs, halnf pressure) { if (proj->mActiveLayer == -1) { return; } - bool max_level = mStroke && mStroke->mPoints.size() > mMaxPoints; + bool max_level = mStroke && mStroke->getPoints().size() > mMaxPoints; if (!pressure || max_level) { if (mStroke) { - unsureReady(mStroke, &proj->mCamera); + ensureReady(mStroke, &proj->mCamera); proj->mLayers[proj->mActiveLayer]->strokes.pushBack(mStroke); mStroke = NULL; } if (max_level) { mStroke = new Stroke(); - mStroke->mCol = mCol; + mStroke->setColor(mCol); - mStroke->mPoints.append(proj->mLayers[proj->mActiveLayer]->strokes.last()->data->mPoints.last()); + mStroke->getPoints().append(proj->mLayers[proj->mActiveLayer]->strokes.last()->data->getPoints().last()); } if (!pressure) { @@ -245,8 +248,8 @@ void PencilBrush::sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) { auto thickness = pressure * (proj->mCamera.project({ 0.f, 0.f }) - proj->mCamera.project({ mSize, 0.f })).length(); bool point_passed = true; - if (mStroke && mStroke->buff().size()) { - auto last_point_2d = proj->mCamera.project(mStroke->buff().last().pos); + if (mStroke && mStroke->getPoints().size()) { + auto last_point_2d = proj->mCamera.project(mStroke->getPoints().last().pos); point_passed = (crs - last_point_2d).length() > mPrecision; } @@ -256,21 +259,24 @@ void PencilBrush::sample(Project* proj, tp::Vec2F crs, tp::halnf pressure) { if (!mStroke) { mStroke = new Stroke(); - mStroke->mCol = mCol; + mStroke->setColor(mCol); } auto point_coords = proj->mCamera.project(crs); - mStroke->buff().append({ point_coords, (tp::halnf) thickness }); - mStroke->updateGpuBuffers(); + mStroke->getPoints().append({ point_coords, (halnf) thickness }); + + // mStroke->updateGpuBuffers(); } -void PencilBrush::draw(Renderer* render, tp::Camera* camera) { +void PencilBrush::draw(Renderer* render, const Camera* camera) const { if (mStroke) { if (mEnableCompression) { - mShowStroke.buff() = mStroke->buff(); - mShowStroke.mCol = mStroke->mCol; - unsureReady(&mShowStroke, camera, 0); - render->drawStroke(&mShowStroke, camera); + Stroke tempDisplayStroke; + tempDisplayStroke.getPoints() = mStroke->getPoints(); + tempDisplayStroke.setColor(mStroke->getColor()); + ensureReady(&tempDisplayStroke, camera, 0); + + render->drawStroke(&tempDisplayStroke, camera); } else { render->drawStroke(mStroke, camera); } @@ -281,7 +287,7 @@ PencilBrush::~PencilBrush() { if (mStroke) delete mStroke; } -Project::Layer::~Layer() { +Layer::~Layer() { for (auto str : strokes) { delete str.data(); } @@ -301,7 +307,7 @@ Project::Project() { mActiveBrush = "pencil"; Stroke* debug = new Stroke(); - debug->mPoints = { { { 0, 0, 0 }, 1 }, { { 1, 1, 1 } , 1} }; + debug->getPoints() = { { { 0, 0, 0 }, 1 }, { { 1, 1, 1 }, 1 } }; debug->updateGpuBuffers(); mLayers.last()->strokes.pushBack(debug); @@ -311,17 +317,34 @@ Project::Project() { vec = mCamera.project({1, 0, 0}); } +void Project::sample(halnf pressure, halnf cameraRatio, Vec2F relativeCameraPos) { + mCamera.setRatio(cameraRatio); + + auto idx = mBrushes.presents(mActiveBrush); + if (idx) { + auto brush = mBrushes.getSlotVal(idx); + + if (brush->mType == "pencil") { + ((tp::PencilBrush*) brush)->mCol = RGBA(1.f); + } + + brush->sample(this, relativeCameraPos, pressure); + } +} + Project::~Project() { for (auto brush : mBrushes) { delete brush->val; } } -Renderer::Renderer(tp::Vec2F size) : +Renderer::Renderer(Vec2F size) : mBuffer(size, 4), mBufferDowncast(size), mShader(".\\rsc\\shaders\\stroke.vert", ".\\rsc\\shaders\\stroke.geom", ".\\rsc\\shaders\\stroke.frag") { + mMaxSize = size; + mMatrixUniform = mShader.getu("MVP"); mColorUniform = mShader.getu("Color"); mRatioUniform = mShader.getu("Ratio"); @@ -329,16 +352,40 @@ Renderer::Renderer(tp::Vec2F size) : mBGColUniform = mShader.getu("BGCol"); } +void Renderer::renderToTexture(const Project* project, Vec2F size) { + size.clamp({ 1, 1 }, mMaxSize); + + setViewport({ 0, 0, size.x, size.y }); + setClearCol(project->mBackgroundColor); + renderBegin(); + + for (auto lay : project->mLayers) { + if (lay.data()->enabled) { + for (auto str : lay.data()->strokes) { + drawStroke(str.data(), &project->mCamera); + } + } + } + + auto idx = project->mBrushes.presents(project->mActiveBrush); + if (idx) { + auto brush = project->mBrushes.getSlotVal(idx); + brush->draw(this, &project->mCamera); + } + + renderEnd(); +} + void Renderer::renderBegin() { mBuffer.beginDraw(); mBuffer.clear(); } -void Renderer::setViewport(tp::RectF viewport) { +void Renderer::setViewport(RectF viewport) { mBuffer.setViewport(viewport); } -void Renderer::drawStroke(Stroke* str, tp::Camera* camera) { +void Renderer::drawStroke(const Stroke* str, const Camera* camera) { //return; glEnable(GL_DEPTH_TEST); @@ -347,30 +394,30 @@ void Renderer::drawStroke(Stroke* str, tp::Camera* camera) { GLint val; glGetIntegerv(GL_SAMPLES, &val); - glBindVertexArray(str->mGl.VertexArrayID); + glBindVertexArray(str->mGPUHandles.VertexArrayID); mShader.bind(); auto cam_mat = camera->calculateTransformationMatrix().transpose(); glUniformMatrix4fv(mMatrixUniform, 1, GL_FALSE, &cam_mat[0][0]); - glUniform4fv(mColorUniform, 1, &str->mCol.r); + glUniform4fv(mColorUniform, 1, &str->mColor.r); glUniform4fv(mBGColUniform, 1, &mBuffer.mClearCol.r); auto ratio = camera->getRatio(); glUniform1fv(mRatioUniform, 1, &ratio); - auto target = tp::halnf(((camera->getTarget() - camera->getPos()).length() - camera->getNear()) + auto target = halnf(((camera->getTarget() - camera->getPos()).length() - camera->getNear()) / (camera->getFar() - camera->getNear())); glUniform1fv(mTargetUniform, 1, &target); // 1st attribute buffer : vertices glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, str->mGl.vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, str->mGPUHandles.vertexbuffer); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void*)0); - glDrawArrays(GL_LINE_STRIP, 0, str->mGl.vbo_len); + glDrawArrays(GL_LINE_STRIP, 0, str->mGPUHandles.vbo_len); glDisableVertexAttribArray(0); @@ -393,15 +440,15 @@ void Renderer::renderEnd() { mBufferDowncast.endDraw(); } -tp::uhalni Renderer::getTextudeId() { +uhalni Renderer::getTextudeId() { return mBufferDowncast.texId(); } -tp::RenderBuffer* Renderer::getBuff() { +RenderBuffer* Renderer::getBuff() { return &mBufferDowncast; } -void Renderer::setClearCol(tp::RGBA col) { +void Renderer::setClearCol(RGBA col) { mBuffer.mClearCol = col; mBufferDowncast.mClearCol = col; } diff --git a/Sketch3D/public/Sketch3D.hpp b/Sketch3D/public/Sketch3D.hpp index 2cb4f9c..da9d247 100644 --- a/Sketch3D/public/Sketch3D.hpp +++ b/Sketch3D/public/Sketch3D.hpp @@ -15,113 +15,40 @@ namespace tp { class Renderer; class Project; + class Stroke; + class Brush; - class Stroke { - - friend Renderer; - - public: - struct Point { - Vec3F pos = { 0, 0, 0 }; - halnf thickness = NULL; - }; - - Buffer mPoints; - RGBA mCol; - - private: - struct GLHandles { - GLuint VertexArrayID = 0; - GLuint vertexbuffer = 0; - GLuint vbo_len = 0; - GLHandles(); - void sendDataToGPU(Buffer* mPoints); - ~GLHandles(); - } mGl; - - public: - - Stroke(); - - void denoisePos(halni passes); - void denoiseThickness(halni passes); - void compress(halnf factor); - void subdiv(halnf precition, Camera* cam, halni passes = 1); - - void updateGpuBuffers(); - - Buffer& buff(); + struct StrokePoint { + Vec3F pos = { 0, 0, 0 }; + halnf thickness = NULL; }; - class Brush { - public: - String mType = "equal"; - Brush() {} - virtual void sample(Project* proj, Vec2F crs, halnf pressure) {} - virtual void draw(Renderer* render, Camera* camera) {} - virtual ~Brush() {} - }; - - class PencilBrush : public Brush { - - halnf mPrecision = 0.001f; - - halni mDenoisePassesPos = 1; - halni mDenoisePassesThick = 3; - halnf mCompressionFactor = 0.0001f; - halni mSubdivPasses = 3; - bool mEnableCompression = true; - - halni mMaxPoints = 100; - - Stroke* mStroke = NULL; - Stroke mShowStroke; - - void unsureReady(Stroke* stroke, Camera* cam, bool debug = false); - - public: - - RGBA mCol = RGBA(1.0f); - halnf mSize = 0.01f; - - PencilBrush(); - virtual void sample(Project* proj, Vec2F crs, halnf pressure) override; - virtual void draw(Renderer* render, Camera* camera) override; - virtual ~PencilBrush(); - }; - - struct EraserBrush : public Brush { - EraserBrush() { mType = "eraser"; } - virtual void sample(Project* proj, Vec2F crs, halnf pressure) override {} - virtual void draw(Renderer* render, Camera* camera) override {} - virtual ~EraserBrush() {} - }; - - class Project { - - public: - - struct Layer { - String name = "new layer"; - List strokes; - bool enabled = true; - ~Layer(); - }; - - Buffer mLayers; - halni mActiveLayer = -1; - - Camera mCamera; - RGBA mBackgroundColor = { 0.22f, 0.22f, 0.25f, 1.f }; - - Map mBrushes; - String mActiveBrush; - - Project(); - ~Project(); + struct StrokeGPUHandles { + GLuint VertexArrayID = 0; + GLuint vertexbuffer = 0; + GLuint vbo_len = 0; + StrokeGPUHandles(); + void sendDataToGPU(Buffer* mPoints); + ~StrokeGPUHandles(); }; class Renderer { + public: + Renderer(Vec2F size); // max render size + ~Renderer(); + + void renderToTexture(const Project* project, Vec2F size); // needed size + + void renderBegin(); + void setViewport(RectF viewport); + void drawStroke(const Stroke* str, const Camera* camera); + void renderEnd(); + + void setClearCol(RGBA col); + uhalni getTextudeId(); + RenderBuffer* getBuff(); + + private: RenderBuffer mBufferDowncast; RenderBuffer mBuffer; RenderShader mShader; @@ -133,96 +60,100 @@ namespace tp { GLuint mTargetUniform = 0; GLuint mBGColUniform = 0; - public: - Renderer(Vec2F size); - - void renderBegin(); - void setViewport(RectF viewport); - void drawStroke(Stroke* str, Camera* camera); - void renderEnd(); - - void setClearCol(RGBA col); - uhalni getTextudeId(); - RenderBuffer* getBuff(); - - ~Renderer(); + Vec2F mMaxSize; }; -}; -/* -void Project::save(File& file) { - file.write(&mCamera); - file.write(&mBackgroundColor); - file.write(&mActiveLayer); + class Stroke { + public: + Stroke(); + void denoisePos(halni passes); + void denoiseThickness(halni passes); + void compress(halnf factor); + void subdiv(halnf precition, const Camera* cam, halni passes = 1); + void updateGpuBuffers(); + Buffer& getPoints(); + const Buffer& getPoints() const; + void setColor(const RGBA& col); + const RGBA& getColor() const; - alni lay_len = mLayers.length(); - file.write(&lay_len); - for (auto layer : mLayers) { - layer.data()->name.save(&file); + private: + Buffer mPoints; + RGBA mColor; - file.write(&layer.data()->enabled); + friend Renderer; + StrokeGPUHandles mGPUHandles; + }; - alni len = layer.data()->strokes.length(); - file.write(&len); - for (auto stiter : layer.data()->strokes) { - stiter->save(file); - } - } -} + struct Layer { + Layer() = default; + ~Layer(); -void Project::load(File& file) { - file.read(&mCamera); - file.read(&mBackgroundColor); - file.read(&mActiveLayer); + String name = "new layer"; + List strokes; // TODO use vector + bool enabled = true; + }; - alni layers_len; - file.read(&layers_len); - mLayers.reserve(layers_len); + class Project { + public: + Project(); + ~Project(); - for (alni idx = 0; idx < layers_len; idx++) { + // pos from -1 to 1 (left ot right bottom to top) + void sample(halnf pressure, halnf cameraRatio, Vec2F relativeCameraPos); - string key; key.load(&file); - auto layer = new Layer(); - layer->name = key; - mLayers[idx] = layer; + public: + Buffer mLayers; + halni mActiveLayer = -1; - file.read(&layer->enabled); + Camera mCamera; + RGBA mBackgroundColor = { 0.22f, 0.22f, 0.25f, 1.f }; - alni len; - file.read(&len); + Map mBrushes; + String mActiveBrush; + }; - for (alni str_idx = 0; str_idx < len; str_idx++) { - auto str = new Stroke(); - layer->strokes.pushBack(str); - layer->strokes.last()->data->load(file); - } - } -} -*/ + class Brush { + public: + String mType = "equal"; + Brush() {} + virtual void sample(Project* proj, Vec2F crs, halnf pressure) {} + virtual void draw(Renderer* render, const Camera* camera) const {} + virtual ~Brush() {} + }; -/* - void Stroke::save(File& file) { - file.write(&mCol); + class PencilBrush : public Brush { + public: + PencilBrush(); + virtual ~PencilBrush(); - alni length = mPoints.length(); - file.write(&length); - for (auto piter : mPoints) { - file.write(&piter.data()); - } - } + virtual void sample(Project* proj, Vec2F crs, halnf pressure) override; + virtual void draw(Renderer* render, const Camera* camera) const override; - void Stroke::load(File& file) { - rgba color; - file.read(&color); + private: + void ensureReady(Stroke* stroke, const Camera* cam, bool debug = false) const; - alni p_len; - file.read(&p_len); + public: + RGBA mCol = RGBA(1.0f); + halnf mSize = 0.01f; - mPoints.reserve(p_len); - for (auto piter : mPoints) { - file.read(&piter.data()); - } + private: + halnf mPrecision = 0.001f; - updateGpuBuffers(); - } - */ \ No newline at end of file + halni mDenoisePassesPos = 1; + halni mDenoisePassesThick = 3; + halnf mCompressionFactor = 0.0001f; + halni mSubdivPasses = 3; + bool mEnableCompression = true; + + halni mMaxPoints = 100; + + Stroke* mStroke = NULL; + }; + + struct EraserBrush : public Brush { + EraserBrush() { mType = "eraser"; } + virtual void sample(Project* proj, Vec2F crs, halnf pressure) override {} + virtual void draw(Renderer* render, const Camera* camera) const override {} + virtual ~EraserBrush() {} + }; +} \ No newline at end of file diff --git a/Sketch3D/public/Sketch3DWidget.hpp b/Sketch3D/public/Sketch3DWidget.hpp index 5dc9a49..ad3d531 100644 --- a/Sketch3D/public/Sketch3DWidget.hpp +++ b/Sketch3D/public/Sketch3DWidget.hpp @@ -8,9 +8,6 @@ namespace tp { template class Sketch3DWidget : public Widget { public: - - Canvas* mCanvas = nullptr; - Sketch3DWidget(Canvas& canvas, Vec2F renderResolution) : mRenderer(renderResolution) { mImage = canvas.createImageFromTextId(mRenderer.getBuff()->texId(), mRenderer.getBuff()->getSize()); @@ -27,54 +24,25 @@ namespace tp { this->mVisible = area.isOverlap(areaParent); if (!this->mVisible) return; - mProject.mCamera.setRatio(this->mArea.w / this->mArea.z); - - // mProject.mBackgroundColor = col_obj_bg->mCol; - if (!this->mArea.isInside(events.getPos())) { return; } halnf pressure = 0.f; - auto idx = mProject.mBrushes.presents(mProject.mActiveBrush); - if (idx) { - auto brush = mProject.mBrushes.getSlotVal(idx); - auto crs = (events.getPos() - this->mArea.pos); - crs.x /= this->mArea.z; - crs.y /= this->mArea.w; - crs = (crs - 0.5) * 2; + auto crs = (events.getPos() - this->mArea.pos); + crs.x /= this->mArea.z; + crs.y /= this->mArea.w; + crs = (crs - 0.5) * 2; - if (brush->mType == "pencil") { - ((tp::PencilBrush*) brush)->mCol = RGBA(1.f); - } + mProject.sample(pressure, this->mArea.w / this->mArea.z, crs); - brush->sample(&mProject, crs, pressure); - } + // mProject.setBackGroundColor(); } void draw(Canvas& canvas) override { - - mRenderer.setViewport({ 0, 0, this->mArea.z, this->mArea.w }); - mRenderer.setClearCol(mProject.mBackgroundColor); - mRenderer.renderBegin(); - - for (auto lay : mProject.mLayers) { - if (lay.data()->enabled) { - for (auto str : lay.data()->strokes) { - mRenderer.drawStroke(str.data(), &mProject.mCamera); - } - } - } - - auto idx = mProject.mBrushes.presents(mProject.mActiveBrush); - if (idx) { - auto brush = mProject.mBrushes.getSlotVal(idx); - brush->draw(&mRenderer, &mProject.mCamera); - } - - mRenderer.renderEnd(); - + if (!this->mVisible) return; + mRenderer.renderToTexture(&mProject, this->mArea.size); canvas.drawImage(this->mArea, &mImage, 0, 1, 12); } @@ -82,5 +50,6 @@ namespace tp { Project mProject; Renderer mRenderer; Canvas::ImageHandle mImage; + Canvas* mCanvas = nullptr; }; } \ No newline at end of file