From dc5553cb8bbdfa73d251a475d5c829ddfafd4929 Mon Sep 17 00:00:00 2001 From: Jiang Ye Date: Tue, 8 Oct 2019 19:07:36 +0900 Subject: [PATCH] can draw sdf --- src/constants.h | 9 +++ src/main | Bin 258196 -> 252612 bytes src/main.cpp | 97 +++++++++++++++++++++++--------- src/sdf.cpp | 115 -------------------------------------- src/sdf.h | 6 -- src/solver.cpp | 143 ++++++++++++++++++++++++++++++++++++++++++++++++ src/solver.h | 9 +++ 7 files changed, 231 insertions(+), 148 deletions(-) diff --git a/src/constants.h b/src/constants.h index 370d5b9..735f1b0 100755 --- a/src/constants.h +++ b/src/constants.h @@ -1,6 +1,9 @@ #pragma once #include "algebra.h" +#include +#include +#include /* ----------------------------------------------------------------------- | OPTIONS @@ -32,6 +35,12 @@ const static float DT = 0.0005f; // Time-step /* ----- GRID ----- */ const static float H_INV = 1.0f; // cell size ? +/* for sdf */ +const static glm::vec2 worldOrigin(0.f, 0.f); +const static float sdfCellSize = H_INV; +const static int sdfWidth = X_GRID; +const static int sdfHeight = Y_GRID; + /* ----- TRANSFER ----- */ #if INTERPOLATION == 1 const static int CUB = 2; diff --git a/src/main b/src/main index 56594302ac894579b3581c79e4d2c6e20f61cf88..3b62e7a186937e24c50746e2d55786b250d3d774 100755 GIT binary patch delta 52707 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 Jr2HUC{1>BdqBH;i delta 58805 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 inParticles = Material::InitializeParticles(); std::vector inPolygons = Polygon::InitializePolygons(); - // std::cout << inPolygons.size() << '\n'; - Simulation = new Solver(inBorders, inNodes, inParticles, inPolygons); + + Simulation->computeSdf(); // for static objects, compute only once } void Update() { @@ -86,10 +87,11 @@ int main(int argc, char **argv) { #else /* [2] : show result on OpenGL window, and record an .mp4 if selected */ - const int frameLimit = 3; + const int frameLimit = 99999; GLFWwindow *window = initGLFWContext(); initGLContext(); + while (!glfwWindowShouldClose(window) && frameNumber < frameLimit) { glClear(GL_COLOR_BUFFER_BIT); @@ -99,42 +101,47 @@ int main(int argc, char **argv) { // AddParticles(); // P2G, compute grid forces, etc. - Update(); + // Update(); // Display frame at desired rate if (t_count % (int)(DT_render / DT) == 0) { Simulation->Draw(); - glfwSwapBuffers(window); - -#if RECORD_VIDEO - std::string dir = "../result/sim"; - // zero padding - std::string num = std::to_string(frameNumber); - num = std::string(4 - num.length(), '0') + num; - std::string output = dir + num + ".png"; + // for testing sdf + drawSdf(window); - // use opencv to save a frame - // the frame size becomes twice from frame 2, - // thus multiplying 2 is needed. - // don't know why - cv::Mat outImg(Y_WINDOW * 2, X_WINDOW * 2, CV_8UC3); - glPixelStorei(GL_PACK_ALIGNMENT, 4); - glReadPixels(0, 0, X_WINDOW * 2, Y_WINDOW * 2, GL_BGR, GL_UNSIGNED_BYTE, - (GLvoid *)outImg.data); - cv::flip(outImg, outImg, 0); - cv::imwrite(output, outImg); - - std::cout << "Frame " << frameNumber << " saved." << '\n'; + glfwSwapBuffers(window); - frameNumber++; -#endif + // #if RECORD_VIDEO + // std::string dir = "../result/sim"; + // + // // zero padding + // std::string num = std::to_string(frameNumber); + // num = std::string(4 - num.length(), '0') + num; + // std::string output = dir + num + ".png"; + // + // // use opencv to save a frame + // // the frame size becomes twice from frame 2, + // // thus multiplying 2 is needed. + // // don't know why + // cv::Mat outImg(Y_WINDOW * 2, X_WINDOW * 2, CV_8UC3); + // glPixelStorei(GL_PACK_ALIGNMENT, 4); + // glReadPixels(0, 0, X_WINDOW * 2, Y_WINDOW * 2, GL_BGR, + // GL_UNSIGNED_BYTE, + // (GLvoid *)outImg.data); + // cv::flip(outImg, outImg, 0); + // cv::imwrite(output, outImg); + // + // std::cout << "Frame " << frameNumber << " saved." << '\n'; + // + // frameNumber++; + // #endif glfwPollEvents(); } // end outer if // Don't forget to reset grid every frame !! - Simulation->ResetGrid(); + // Simulation->ResetGrid(); t_count++; } // end while @@ -187,3 +194,39 @@ void initGLContext() { glClearColor(.659f, .694f, .82f, .0f); glClear(GL_COLOR_BUFFER_BIT); } + +// for testing sdf +void drawSdf(GLFWwindow *wnd) { + double xpos, ypos; + glfwGetCursorPos(wnd, &xpos, &ypos); + + float fx, fy; + fx = xpos / (float)X_WINDOW; + fy = ypos / (float)Y_WINDOW; + + // Note: (0, 0) is at right-bottom + float wx, wy; + wx = fx * X_GRID; + wy = (1.f - fy) * Y_GRID; + + // for test + // draw sdf gradient at a given point + glm::vec2 start = glm::vec2(wx, wy); + float dist = Simulation->getDistance(start); + glm::vec2 grad = Simulation->getGradient(start); + glm::vec2 end = start + dist * grad; + + // start.x = start.x / (float)X_GRID * (float)X_WINDOW; + // start.y = start.y / (float)Y_GRID * (float)Y_WINDOW; + // + // end.x = end.x / (float)X_GRID * (float)X_WINDOW; + // end.y = end.y / (float)Y_GRID * (float)Y_WINDOW; + + glLineWidth(4); + glColor3f(1.f, 0.f, 0.f); + + glBegin(GL_LINES); + glVertex2f(start.x, start.y); // start point + glVertex2f(end.x, end.y); // end point + glEnd(); +} diff --git a/src/sdf.cpp b/src/sdf.cpp index df710ba..10dc048 100644 --- a/src/sdf.cpp +++ b/src/sdf.cpp @@ -1,8 +1,6 @@ #include "sdf.h" #include "solver.h" -glm::vec2 worldOrigin(0.f, 0.f); - /* Functions in class Polygon */ void Polygon::computeAabb() { lb = vertices[0]; @@ -97,116 +95,3 @@ void Polygon::DrawPolygon() { glEnd(); } /* end Functions in class Polygon */ - -bool intersect(glm::vec2 p1, glm::vec2 p2, glm::vec2 p3, glm::vec2 p4) { - glm::vec3 a(p1, 0), b(p2, 0), c(p3, 0), d(p4, 0); - - float crossAcAb, crossAbAd, crossDaDc, crossDcDb; - crossAcAb = glm::cross(c - a, b - a).z; - crossAbAd = glm::cross(b - a, d - a).z; - crossDaDc = glm::cross(a - d, c - d).z; - crossDcDb = glm::cross(c - d, b - d).z; - - if (crossAcAb * crossAbAd > 0 && crossDaDc * crossDcDb > 0) { - return true; - } else { - return false; - } -} - -bool inside_polygon(glm::vec2 p, Polygon &poly) { - int count = 0; - glm::vec2 q(1234567.f, 1234567.f); // a point at the infinity - int len = poly.vertices.size(); - - for (int i = 0; i < len; i++) { - glm::vec2 &start = poly.vertices[i]; - glm::vec2 &end = poly.vertices[(i + 1) % len]; - count += intersect(p, q, start, end); - } - - return count % 2 == 1; -} - -float nearest_distance(glm::vec2 p, Polygon &poly) { - float dist = 9999.f; - int len = poly.vertices.size(); - - for (int i = 0; i < len; i++) { - glm::vec2 &a = poly.vertices[i]; - glm::vec2 &b = poly.vertices[(i + 1) % len]; - - //当前处理的边定义为 ab - glm::vec2 ab = b - a; - float abLength = glm::length(ab); - glm::vec2 dir = glm::normalize(ab); - - //求点 p 在边 ab 上的投影点 q - //于是,线段 pq 的长度就是 p 点的有向距离 - glm::vec2 ap = p - a; - float frac = glm::dot(ap, dir); - frac = glm::clamp(frac, 0.f, abLength); - glm::vec2 q = a + frac * dir; - glm::vec2 pq = q - p; - - dist = glm::min(dist, length(pq)); - } - - return dist; -} - -// p is world position -// float getDistance(glm::vec2 p) { -// // world position to sdf index -// int idx_x, idx_y; -// idx_x = int(glm::floor(p.x / sdfCellSize)); -// idx_y = int(glm::floor(p.y / sdfCellSize)); -// -// if (idx_x < 0 || idx_x > sdfWidth - 1) { -// return 9999.f; -// } else if (idx_y < 0.f || idx_y > sdfHeight - 1) { -// return 9999.f; -// } else { -// return grid.sdf.at(Point(idx_x, idx_y)); -// } -// } - -// p is world position - -void computeSdf(int sdfWidth, int sdfHeight, float sdfCellSize, - std::vector &polygons, Solver &slv) { - // compute sdf for (sdfWidth * sdfHeight) world space points - // the interval between two adjacent points is sdfCellSize - for (int x = 0; x < sdfWidth; x++) { - for (int y = 0; y < sdfHeight; y++) { - // std::cout << x << ", " << y << '\n'; - - // world space point - glm::vec2 p = worldOrigin + glm::vec2(sdfCellSize * x, sdfCellSize * y); - - float fDist = 9999.f; - float temp = 0.f; - - for (int i = 0; i < polygons.size(); i++) { - // std::cout << i << '\n'; - temp = (inside_polygon(p, polygons[i])) ? -1.f : 1.f; - temp *= nearest_distance(p, polygons[i]); - // std::cout << "here" << '\n'; - - // fDist = glm::min(temp, fDist); - if (temp < fDist) { - fDist = temp; - - // change to Node - // the nearest polygon to this node - // grid.polyPtrs.set(y, x, polygons[i]); - } - } - - // save sdf distance - int idx = x + y * (sdfWidth - 1); // # of nodes in a row is (sdfWidth - 1) - slv.nodes[idx].sdfDist = fDist; - // std::cout << "(" << x << ", " << y << ") distance = " << fDist << '\n'; - } - } -} diff --git a/src/sdf.h b/src/sdf.h index 2320b1a..e07cf9e 100644 --- a/src/sdf.h +++ b/src/sdf.h @@ -10,8 +10,6 @@ #include #include -extern glm::vec2 worldOrigin; - class Polygon { public: std::vector vertices; @@ -51,7 +49,3 @@ class Polygon { return polys; } }; // end class Polygon - -bool intersect(glm::vec2, glm::vec2, glm::vec2, glm::vec2); -bool inside_polygon(glm::vec2, Polygon &); -float nearest_distance(glm::vec2, Polygon &); diff --git a/src/solver.cpp b/src/solver.cpp index d61a34c..5293763 100755 --- a/src/solver.cpp +++ b/src/solver.cpp @@ -16,6 +16,149 @@ Solver::Solver(const std::vector &inBorders, polylen = polygons.size(); } +/* Functions for computing sdf */ +void Solver::computeSdf() { + // compute sdf for (sdfWidth * sdfHeight) world space points + // the interval between two adjacent points is sdfCellSize + for (int x = 0; x < sdfWidth; x++) { + for (int y = 0; y < sdfHeight; y++) { + // std::cout << x << ", " << y << '\n'; + + // world space point + glm::vec2 p = worldOrigin + glm::vec2(sdfCellSize * x, sdfCellSize * y); + + float fDist = 9999.f; + float temp = 0.f; + + for (int i = 0; i < polygons.size(); i++) { + // std::cout << i << '\n'; + temp = (inside_polygon(p, polygons[i])) ? -1.f : 1.f; + temp *= nearest_distance(p, polygons[i]); + // std::cout << "here" << '\n'; + + // fDist = glm::min(temp, fDist); + if (temp < fDist) { + fDist = temp; + + // change to Node + // the nearest polygon to this node + // grid.polyPtrs.set(y, x, polygons[i]); + } + } + + // save sdf distance + int idx = x + y * (sdfWidth - 1); // # of nodes in a row is (sdfWidth - 1) + nodes[idx].sdfDist = fDist; + // std::cout << "(" << x << ", " << y << ") distance = " << fDist << '\n'; + } + } +} + +bool Solver::intersect(glm::vec2 p1, glm::vec2 p2, glm::vec2 p3, glm::vec2 p4) { + glm::vec3 a(p1, 0), b(p2, 0), c(p3, 0), d(p4, 0); + + float crossAcAb, crossAbAd, crossDaDc, crossDcDb; + crossAcAb = glm::cross(c - a, b - a).z; + crossAbAd = glm::cross(b - a, d - a).z; + crossDaDc = glm::cross(a - d, c - d).z; + crossDcDb = glm::cross(c - d, b - d).z; + + if (crossAcAb * crossAbAd > 0 && crossDaDc * crossDcDb > 0) { + return true; + } else { + return false; + } +} + +bool Solver::inside_polygon(glm::vec2 p, Polygon &poly) { + int count = 0; + glm::vec2 q(1234567.f, 1234567.f); // a point at the infinity + int len = poly.vertices.size(); + + for (int i = 0; i < len; i++) { + glm::vec2 &start = poly.vertices[i]; + glm::vec2 &end = poly.vertices[(i + 1) % len]; + count += intersect(p, q, start, end); + } + + return count % 2 == 1; +} + +float Solver::nearest_distance(glm::vec2 p, Polygon &poly) { + float dist = 9999.f; + int len = poly.vertices.size(); + + for (int i = 0; i < len; i++) { + glm::vec2 &a = poly.vertices[i]; + glm::vec2 &b = poly.vertices[(i + 1) % len]; + + //当前处理的边定义为 ab + glm::vec2 ab = b - a; + float abLength = glm::length(ab); + glm::vec2 dir = glm::normalize(ab); + + //求点 p 在边 ab 上的投影点 q + //于是,线段 pq 的长度就是 p 点的有向距离 + glm::vec2 ap = p - a; + float frac = glm::dot(ap, dir); + frac = glm::clamp(frac, 0.f, abLength); + glm::vec2 q = a + frac * dir; + glm::vec2 pq = q - p; + + dist = glm::min(dist, length(pq)); + } + + return dist; +} + +// p is world position +float Solver::getDistance(glm::vec2 p) { + + // world position to sdf index + int idx_x, idx_y; + idx_x = int(glm::floor(p.x / sdfCellSize)); + idx_y = int(glm::floor(p.y / sdfCellSize)); + + if (idx_x < 0 || idx_x > sdfWidth - 1) { + return 9999.f; + } else if (idx_y < 0.f || idx_y > sdfHeight - 1) { + return 9999.f; + } else { + int idx = idx_x + idx_y * (sdfWidth - 1); + return nodes[idx].sdfDist; + } +} + +// p is world position +glm::vec2 Solver::getGradient(glm::vec2 p) { + glm::vec2 gd; + + // world position to sdf position + glm::vec2 sdfPos, sdfPosFloor; + sdfPos = p / sdfCellSize; + sdfPosFloor = glm::floor(sdfPos); + + float fx, fy; + fx = sdfPos.x - sdfPosFloor.x; + fy = sdfPos.y - sdfPosFloor.y; + + float temp1 = getDistance(glm::vec2(p.x + 1.f, p.y)) - + getDistance(glm::vec2(p.x - 1.f, p.y)); + float temp2 = getDistance(glm::vec2(p.x + 1.f, p.y + 1.f)) - + getDistance(glm::vec2(p.x - 1.f, p.y + 1.f)); + gd.x = glm::lerp(temp1, temp2, fy); + + float temp3 = getDistance(glm::vec2(p.x, p.y + 1.f)) - + getDistance(glm::vec2(p.x, p.y - 1.f)); + float temp4 = getDistance(glm::vec2(p.x + 1.f, p.y + 1.f)) - + getDistance(glm::vec2(p.x + 1.f, p.y - 1.f)); + gd.y = glm::lerp(temp3, temp4, fx); + + gd = glm::normalize(-gd); + + return gd; +} + /* ----------------------------------------------------------------------- | MATERIAL POINT METHOD ALGORITHM | diff --git a/src/solver.h b/src/solver.h index 264de7f..9a2b86d 100755 --- a/src/solver.h +++ b/src/solver.h @@ -2,6 +2,7 @@ #include "node.h" #include "particle.h" +#include "constants.h" #include "sdf.h" #include #include @@ -35,6 +36,14 @@ class Solver { void UpdateParticles(); void ResetGrid(); + /* Functions for computing sdf */ + void computeSdf(); + bool intersect(glm::vec2, glm::vec2, glm::vec2, glm::vec2); + bool inside_polygon(glm::vec2, Polygon &); + float nearest_distance(glm::vec2, Polygon &); + float getDistance(glm::vec2); + glm::vec2 getGradient(glm::vec2); + void Draw(); // Draw particles, border and nodes (if selected) void WriteToFile( int frame); // Write point cloud coordinates to .ply file (Houdini)