From 56dfc5e3bc747b8e44c4a2f1819792a59c5545f7 Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Fri, 25 Sep 2020 16:11:36 -0300 Subject: [PATCH 1/8] Adding .gitignore --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88213e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# C extensions +*.so +*.o +*.pyc + +utils/fast_render/build From 1e7630f24c1b628e26d20be9694004b51f8c56a2 Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Fri, 25 Sep 2020 16:12:06 -0300 Subject: [PATCH 2/8] Adding fast_render cpp code --- utils/fast_render/CMakeLists.txt | 17 +++++++++++ utils/fast_render/__init__.py | 0 utils/fast_render/fast_render.py | 37 ++++++++++++++++++++++++ utils/fast_render/src/render.cpp | 49 ++++++++++++++++++++++++++++++++ utils/fast_render/src/render.h | 17 +++++++++++ 5 files changed, 120 insertions(+) create mode 100644 utils/fast_render/CMakeLists.txt create mode 100644 utils/fast_render/__init__.py create mode 100644 utils/fast_render/fast_render.py create mode 100644 utils/fast_render/src/render.cpp create mode 100644 utils/fast_render/src/render.h diff --git a/utils/fast_render/CMakeLists.txt b/utils/fast_render/CMakeLists.txt new file mode 100644 index 0000000..7ee5f2e --- /dev/null +++ b/utils/fast_render/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.5) + +project(fast_render VERSION 0.0.1) + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wfatal-errors -O2") + +include_directories( + "src/" +) + +file(GLOB all_fast_render_src + "src/*.cpp" +) + +add_library(fast_render SHARED ${all_fast_render_src}) diff --git a/utils/fast_render/__init__.py b/utils/fast_render/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/fast_render/fast_render.py b/utils/fast_render/fast_render.py new file mode 100644 index 0000000..c5d9ac4 --- /dev/null +++ b/utils/fast_render/fast_render.py @@ -0,0 +1,37 @@ +import ctypes +import numpy as np +from numpy.ctypeslib import ndpointer + +lib = ctypes.CDLL('./build/libfast_render.so') + +c_render_texture_loop = lib.render_texture_loop +c_render_texture_loop.argtypes = [ + ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), # tri_depth + ctypes.c_int, + ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), # tri_tex + ctypes.c_int, + ctypes.c_int, + ndpointer(ctypes.c_int, flags='C_CONTIGUOUS'), # triangles + ctypes.c_int, + ctypes.c_int, + ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), # vertices + ctypes.c_int, + ctypes.c_int, + ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), # depth_buffer + ctypes.c_int, + ctypes.c_int, + ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), # image + ctypes.c_int, + ctypes.c_int, +] + + +def render_texture_loop(tri_depth, tri_tex, triangles, vertices, depth_buffer, image): + c_render_texture_loop( + tri_depth, tri_depth.shape[0], + tri_tex, tri_tex.shape[1], tri_tex.shape[0], + triangles, triangles.shape[1], triangles.shape[0], + vertices, vertices.shape[1], vertices.shape[0], + depth_buffer, depth_buffer.shape[1], depth_buffer.shape[0], + image, image.shape[1], image.shape[0] + ) diff --git a/utils/fast_render/src/render.cpp b/utils/fast_render/src/render.cpp new file mode 100644 index 0000000..356c1c6 --- /dev/null +++ b/utils/fast_render/src/render.cpp @@ -0,0 +1,49 @@ +#include "render.h" + +void render_texture_loop(const double *tri_depth, int tri_depth_height, + const double *tri_tex, int tri_tex_width, int tri_tex_height, + const int *triangles, int triangles_width, int triangles_height, + const double *vertices, int vertices_width, int vertices_height, + double *depth_buffer, int depth_buffer_width, int depth_buffer_height, + double *image, int image_width, int image_height) +{ + for (int i=0; i depth_buffer[v*depth_buffer_width + u]) { + if (true) { //isPointInTri(u, v, v1_u, v2_u, v3_u, v1_v, v2_v, v3_v)) { + depth_buffer[v*depth_buffer_width + u] = tri_depth[i]; + for (int aux=0; aux +#include +#include // ceil +#include // min max + +extern "C" { + void render_texture_loop( + const double *tri_depth, int tri_depth_height, + const double *tri_tex, int tri_tex_width, int tri_tex_height, + const int *triangles, int triangles_width, int triangles_height, + const double *vertices, int vertices_width, int vertices_height, + double *depth_buffer, int depth_buffer_width, int depth_buffer_height, + double *image, int image_width, int image_height + ); +} From d286de0c06d547daefa1f14c5540e0c0e7ebb1e3 Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Fri, 25 Sep 2020 17:11:52 -0300 Subject: [PATCH 3/8] Implementing PointInTriangle function and removing some debug code --- utils/fast_render/fast_render.py | 2 +- utils/fast_render/src/render.cpp | 12 +++++++++- utils/render.py | 39 ++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/utils/fast_render/fast_render.py b/utils/fast_render/fast_render.py index c5d9ac4..f2ae3cd 100644 --- a/utils/fast_render/fast_render.py +++ b/utils/fast_render/fast_render.py @@ -2,7 +2,7 @@ import numpy as np from numpy.ctypeslib import ndpointer -lib = ctypes.CDLL('./build/libfast_render.so') +lib = ctypes.CDLL('./utils/fast_render/build/libfast_render.so') c_render_texture_loop = lib.render_texture_loop c_render_texture_loop.argtypes = [ diff --git a/utils/fast_render/src/render.cpp b/utils/fast_render/src/render.cpp index 356c1c6..ab0fa1f 100644 --- a/utils/fast_render/src/render.cpp +++ b/utils/fast_render/src/render.cpp @@ -1,5 +1,15 @@ #include "render.h" + +bool PointInTriangle(double p_x, double p_y, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y) { + float A = 1/2 * (-p1_y * p2_x + p0_y * (-p1_x + p2_x) + p0_x * (p1_y - p2_y) + p1_x * p2_y); + float sign = A < 0 ? -1 : 1; + float s = (p0_y * p2_x - p0_x * p2_y + (p2_y - p0_y) * p_x + (p0_x - p2_x) * p_y) * sign; + float t = (p0_x * p1_y - p0_y * p1_x + (p0_y - p1_y) * p_x + (p1_x - p0_x) * p_y) * sign; + + return s > 0 && t > 0 && (s + t) < 2 * A * sign; +} + void render_texture_loop(const double *tri_depth, int tri_depth_height, const double *tri_tex, int tri_tex_width, int tri_tex_height, const int *triangles, int triangles_width, int triangles_height, @@ -35,7 +45,7 @@ void render_texture_loop(const double *tri_depth, int tri_depth_height, for (int u = umin; u depth_buffer[v*depth_buffer_width + u]) { - if (true) { //isPointInTri(u, v, v1_u, v2_u, v3_u, v1_v, v2_v, v3_v)) { + if (PointInTriangle(u, v, v1_u, v2_u, v3_u, v1_v, v2_v, v3_v)) { depth_buffer[v*depth_buffer_width + u] = tri_depth[i]; for (int aux=0; aux depth_buffer[v, u] and isPointInTri([u,v], vertices[:2, tri]): + depth_buffer[v, u] = tri_depth[i] + image[v, u, :] = tri_tex[:, i] - for u in range(umin, umax+1): - for v in range(vmin, vmax+1): - if tri_depth[i] > depth_buffer[v, u] and isPointInTri([u,v], vertices[:2, tri]): - depth_buffer[v, u] = tri_depth[i] - image[v, u, :] = tri_tex[:, i] return image From 418de0996caa7813da9794f3850fd279a7fab3bd Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Fri, 25 Sep 2020 17:12:09 -0300 Subject: [PATCH 4/8] Adding simple shell script to compile the lib --- build.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 build.sh diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..8c624ac --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +cd utils/fast_render +mkdir build +cd build +cmake .. +make From a09e4dcda525746fd04990c94a399942195e5d3a Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Fri, 25 Sep 2020 18:08:14 -0300 Subject: [PATCH 5/8] Updating README --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index f7bfcd3..832beca 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,12 @@ What you can custom: you can refer to [c++ version](https://github.com/YadiraF/face3d/blob/master/face3d/mesh/render.py). + Another alternative is to use the C++ already in this repo, integrated with ctypes. You must install both CMake and a C++ compiler, then run the following command: + ``` + sh build.sh + ``` + This code only implements the hotpath of rendering the face depth map. The speedup from a 256x256 image was from 2681ms to 1.8ms, quite a difference. + c. other parts like detecting face, writing obj the best way is to rewrite them in c++. From f3b74410fd1fd714aa9193a628d8b6309209aab6 Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Wed, 30 Sep 2020 16:23:10 -0300 Subject: [PATCH 6/8] Fixing PointInTriangle --- utils/fast_render/src/render.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/utils/fast_render/src/render.cpp b/utils/fast_render/src/render.cpp index ab0fa1f..f0e0aa1 100644 --- a/utils/fast_render/src/render.cpp +++ b/utils/fast_render/src/render.cpp @@ -1,13 +1,16 @@ #include "render.h" -bool PointInTriangle(double p_x, double p_y, double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y) { - float A = 1/2 * (-p1_y * p2_x + p0_y * (-p1_x + p2_x) + p0_x * (p1_y - p2_y) + p1_x * p2_y); - float sign = A < 0 ? -1 : 1; - float s = (p0_y * p2_x - p0_x * p2_y + (p2_y - p0_y) * p_x + (p0_x - p2_x) * p_y) * sign; - float t = (p0_x * p1_y - p0_y * p1_x + (p0_y - p1_y) * p_x + (p1_x - p0_x) * p_y) * sign; - - return s > 0 && t > 0 && (s + t) < 2 * A * sign; +bool PointInTriangle(double p_x, double p_y, double p0_x, double p1_x, double p2_x, double p0_y, double p1_y, double p2_y) { + // Original code from here: https://github.com/SebLague/Gamedev-Maths/blob/master/PointInTriangle.cs + double s1 = p2_y - p0_y; + double s2 = p2_x - p0_x; + double s3 = p1_y - p0_y; + double s4 = p_y - p0_y; + + double w1 = (p0_x * s1 + s4 * s2 - p_x * s1) / (s3 * s2 - (p1_x-p0_x) * s1); + double w2 = (s4- w1 * s3) / s1; + return w1 >= 0 && w2 >= 0 && (w1 + w2) <= 1; } void render_texture_loop(const double *tri_depth, int tri_depth_height, @@ -45,7 +48,7 @@ void render_texture_loop(const double *tri_depth, int tri_depth_height, for (int u = umin; u depth_buffer[v*depth_buffer_width + u]) { - if (PointInTriangle(u, v, v1_u, v2_u, v3_u, v1_v, v2_v, v3_v)) { + if (PointInTriangle((double)u, (double)v, v1_u, v2_u, v3_u, v1_v, v2_v, v3_v)) { depth_buffer[v*depth_buffer_width + u] = tri_depth[i]; for (int aux=0; aux Date: Thu, 1 Oct 2020 14:38:32 -0300 Subject: [PATCH 7/8] Slightly improving the code --- utils/render.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/utils/render.py b/utils/render.py index d85abb1..14fccd0 100644 --- a/utils/render.py +++ b/utils/render.py @@ -5,8 +5,11 @@ import numpy as np try: from utils.fast_render import fast_render + using_fast_render = True except BaseException as e: - print(e) + print("INFO - You can run 'sh build.sh' to build a faster " + "rendering function for the depthmap images") + using_fast_render = False def isPointInTri(point, tri_points): ''' Judge whether the point is in the triangle @@ -106,9 +109,9 @@ def render_texture(vertices, colors, triangles, h, w, c = 3): triangles = np.ascontiguousarray(triangles) vertices = np.ascontiguousarray(vertices) - try: + if using_fast_render: fast_render.render_texture_loop(tri_depth, tri_tex, triangles, vertices, depth_buffer, image) - except: + else: for i in range(triangles.shape[1]): tri = triangles[:, i] # 3 vertex indices From 9bd3a16f9f2cd2f9e8a1c9c713f58b7a8d0d9449 Mon Sep 17 00:00:00 2001 From: Guilherme Fickel Date: Thu, 1 Oct 2020 16:39:47 -0300 Subject: [PATCH 8/8] Adding support to multiple channels image --- utils/fast_render/fast_render.py | 7 ++++++- utils/fast_render/src/render.cpp | 6 ++++-- utils/fast_render/src/render.h | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/utils/fast_render/fast_render.py b/utils/fast_render/fast_render.py index f2ae3cd..a39de4d 100644 --- a/utils/fast_render/fast_render.py +++ b/utils/fast_render/fast_render.py @@ -27,11 +27,16 @@ def render_texture_loop(tri_depth, tri_tex, triangles, vertices, depth_buffer, image): + if len(image.shape) == 2: + image_channels = 1 + else: + image_channels = image.shape[2] + c_render_texture_loop( tri_depth, tri_depth.shape[0], tri_tex, tri_tex.shape[1], tri_tex.shape[0], triangles, triangles.shape[1], triangles.shape[0], vertices, vertices.shape[1], vertices.shape[0], depth_buffer, depth_buffer.shape[1], depth_buffer.shape[0], - image, image.shape[1], image.shape[0] + image, image.shape[1], image.shape[0], image_channels ) diff --git a/utils/fast_render/src/render.cpp b/utils/fast_render/src/render.cpp index f0e0aa1..ecdbe08 100644 --- a/utils/fast_render/src/render.cpp +++ b/utils/fast_render/src/render.cpp @@ -18,7 +18,7 @@ void render_texture_loop(const double *tri_depth, int tri_depth_height, const int *triangles, int triangles_width, int triangles_height, const double *vertices, int vertices_width, int vertices_height, double *depth_buffer, int depth_buffer_width, int depth_buffer_height, - double *image, int image_width, int image_height) + double *image, int image_width, int image_height, int image_channels) { for (int i=0; i