diff --git a/example/cam2mat.cpp b/example/cam2mat.cpp index 5ee571f..bddbb20 100644 --- a/example/cam2mat.cpp +++ b/example/cam2mat.cpp @@ -1,10 +1,10 @@ -#include +#include #include #include #include #include #include -#include +#include int parse_aspect_ratio(const char* aspect_str, int *width, int *height) diff --git a/include/pcprep/aabb.h b/include/pcprep/aabb.h index ea21690..aa2bcd2 100644 --- a/include/pcprep/aabb.h +++ b/include/pcprep/aabb.h @@ -6,8 +6,8 @@ extern "C" { #endif +#include "pcprep/defs.h" #include "pcprep/mesh.h" -#include "pcprep/pcprep_export.h" #include "pcprep/vec3f.h" /** @@ -16,11 +16,18 @@ extern "C" * Defined by its min and max corners. * @see aabb.h */ - typedef struct aabb_t + struct pcp_aabb_t { - vec3f_t min; ///< Minimum (x, y, z) - vec3f_t max; ///< Maximum (x, y, z) - } aabb_t; + pcp_vec3f_t min; ///< Minimum (x, y, z) + pcp_vec3f_t max; ///< Maximum (x, y, z) + pcp_ret_t (*to_mesh)(pcp_aabb_t *self, pcp_mesh_t *mesh); + }; + + PCPREP_EXPORT + pcp_ret_t pcp_aabb_init(pcp_aabb_t *self); + + PCPREP_EXPORT + pcp_ret_t pcp_aabb_free(pcp_aabb_t *self); /** * @brief Constructs a triangle mesh from an axis-aligned bounding @@ -32,8 +39,7 @@ extern "C" * @param mesh Output pointer to the resulting mesh. * @return 0 on success, non-zero on failure. */ - PCPREP_EXPORT - int aabb_to_mesh(aabb_t aabb, mesh_t *mesh); + pcp_ret_t pcp_aabb_to_mesh(pcp_aabb_t *self, pcp_mesh_t *mesh); #ifdef __cplusplus } diff --git a/include/pcprep/canvas.h b/include/pcprep/canvas.h index 7417431..c9f38c2 100644 --- a/include/pcprep/canvas.h +++ b/include/pcprep/canvas.h @@ -1,22 +1,20 @@ #ifndef CANVAS_H #define CANVAS_H -#include "pcprep/core.h" -#include "pcprep/pcprep_export.h" +#include "pcprep/defs.h" +#include "pcprep/utils.h" #include "pcprep/vec3uc.h" -typedef struct canvas_t canvas_t; - /** * @brief holds the data of a virtual screen to be drawn. * * */ -struct canvas_t +struct pcp_canvas_t { size_t width; size_t height; - vec3uc_t bg_col; + pcp_vec3uc_t bg_col; unsigned char *pixels; float **min_z_value; @@ -31,40 +29,37 @@ struct canvas_t unsigned int matrix_id; #endif - void (*draw_points)( - canvas_t *, float *, float *, unsigned char *, size_t); - void (*clear)(canvas_t *); + pcp_ret_t (*draw_points)( + pcp_canvas_t *, float *, float *, unsigned char *, size_t); + pcp_ret_t (*clear)(pcp_canvas_t *); }; PCPREP_EXPORT -int canvas_init(canvas_t *cv, - size_t width, - size_t height, +pcp_ret_t pcp_canvas_init(pcp_canvas_t *cv, + size_t width, + size_t height, #ifdef HAVE_GPU - char *vert_shader, - char *frag_shader, + char *vert_shader, + char *frag_shader, #endif - vec3uc_t bg_col); + pcp_vec3uc_t bg_col); PCPREP_EXPORT -int canvas_free(canvas_t *cv); +pcp_ret_t pcp_canvas_free(pcp_canvas_t *cv); #ifdef HAVE_GPU -PCPREP_EXPORT -void canvas_draw_points_gpu(canvas_t *cv, - float *mvp, - float *pos, - unsigned char *rgb, - size_t count); +pcp_ret_t pcp_canvas_draw_points_gpu(pcp_canvas_t *cv, + float *mvp, + float *pos, + unsigned char *rgb, + size_t count); #endif -PCPREP_EXPORT -void canvas_draw_points_cpu(canvas_t *cv, - float *mvp, - float *pos, - unsigned char *rgb, - size_t count); +pcp_ret_t pcp_canvas_draw_points_cpu(pcp_canvas_t *cv, + float *mvp, + float *pos, + unsigned char *rgb, + size_t count); -PCPREP_EXPORT -void canvas_clear(canvas_t *cv); +pcp_ret_t pcp_canvas_clear(pcp_canvas_t *cv); #endif diff --git a/include/pcprep/defs.h b/include/pcprep/defs.h new file mode 100644 index 0000000..116850f --- /dev/null +++ b/include/pcprep/defs.h @@ -0,0 +1,29 @@ +#ifndef PCPREP_DEFS_H +#define PCPREP_DEFS_H + +#include "pcprep/pcprep_export.h" +#include +#include +#include +#include + +typedef uint32_t pcp_ret_t; + +#define PCPREP_RET_FAIL 0x00 +#define PCPREP_RET_SUCCESS 0x01 + +#ifdef __cplusplus +#define PCPREP_NULL nullptr +#else +#define PCPREP_NULL ((void *)0) +#endif + +typedef struct pcp_aabb_t pcp_aabb_t; +typedef struct pcp_canvas_t pcp_canvas_t; +typedef struct pcp_mesh_t pcp_mesh_t; +typedef struct pcp_point_cloud_t pcp_point_cloud_t; +typedef struct pcp_vec3f_t pcp_vec3f_t; +typedef struct pcp_vec3u_t pcp_vec3u_t; +typedef struct pcp_vec3uc_t pcp_vec3uc_t; + +#endif diff --git a/include/pcprep/mesh.h b/include/pcprep/mesh.h index a60d744..fb18492 100644 --- a/include/pcprep/mesh.h +++ b/include/pcprep/mesh.h @@ -7,30 +7,44 @@ extern "C" #endif -#include "pcprep/pcprep_export.h" +#include "pcprep/defs.h" #include #include - typedef struct mesh_t + struct pcp_mesh_t { float *pos; uint32_t num_verts; uint32_t *indices; uint32_t num_indices; - } mesh_t; + pcp_ret_t (*alloc)(pcp_mesh_t *self, + uint32_t num_verts, + uint32_t num_indices); + pcp_ret_t (*load)(pcp_mesh_t *self, const char *filename); + pcp_ret_t (*write)(pcp_mesh_t *self, + const char *filename, + int binary); + pcp_ret_t (*get_screen_ratio)(pcp_mesh_t *self, + float *mvp, + float *screen_ratio); + }; PCPREP_EXPORT - int mesh_init(mesh_t *mesh, - uint32_t num_verts, - uint32_t num_indices); + pcp_ret_t pcp_mesh_init(pcp_mesh_t *self); PCPREP_EXPORT - int mesh_free(mesh_t *mesh); - PCPREP_EXPORT - int mesh_load(mesh_t *mesh, const char *filename); - PCPREP_EXPORT - int mesh_write(mesh_t mesh, const char *filename, int binary); - PCPREP_EXPORT - int mesh_screen_ratio(mesh_t mesh, float *mvp, float *screen_ratio); + pcp_ret_t pcp_mesh_free(pcp_mesh_t *self); + + pcp_ret_t pcp_mesh_alloc(pcp_mesh_t *self, + uint32_t num_verts, + uint32_t num_indices); + pcp_ret_t pcp_mesh_load(pcp_mesh_t *self, const char *filename); + + pcp_ret_t + pcp_mesh_write(pcp_mesh_t *self, const char *filename, int binary); + + pcp_ret_t pcp_mesh_get_screen_ratio(pcp_mesh_t *self, + float *mvp, + float *screen_ratio); #ifdef __cplusplus } diff --git a/include/pcprep/point_cloud.h b/include/pcprep/point_cloud.h new file mode 100644 index 0000000..ab3d570 --- /dev/null +++ b/include/pcprep/point_cloud.h @@ -0,0 +1,95 @@ +#ifndef POINT_CLOUD_H +#define POINT_CLOUD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include +#include + + struct pcp_point_cloud_t + { + float *pos; + uint8_t *rgb; + size_t size; // number of points, *pos have size*3 elements + pcp_ret_t (*alloc)(pcp_point_cloud_t *self, size_t size); + pcp_ret_t (*load)(pcp_point_cloud_t *self, const char *filename); + pcp_ret_t (*write)(pcp_point_cloud_t *self, + const char *filename, + int binary); + pcp_ret_t (*get_min)(pcp_point_cloud_t *self, pcp_vec3f_t *min); + pcp_ret_t (*get_max)(pcp_point_cloud_t *self, pcp_vec3f_t *max); + pcp_ret_t (*tile)(pcp_point_cloud_t *self, + int n_x, + int n_y, + int n_z, + pcp_point_cloud_t **tiles); + pcp_ret_t (*sample)(pcp_point_cloud_t *self, + float ratio, + unsigned char strategy, + pcp_point_cloud_t *out); + pcp_ret_t (*remove_dupplicates)(pcp_point_cloud_t *self, + pcp_point_cloud_t *out); + pcp_ret_t (*voxelize)(pcp_point_cloud_t *self, + float voxel_size, + pcp_point_cloud_t *out); + pcp_ret_t (*get_pixel_per_tile)(pcp_point_cloud_t *self, + int nx, + int ny, + int nz, + int width, + int height, + float *mvp, + int *pixel_count); + }; + + PCPREP_EXPORT + pcp_ret_t pcp_point_cloud_init(pcp_point_cloud_t *self); + PCPREP_EXPORT + pcp_ret_t pcp_point_cloud_free(pcp_point_cloud_t *pc); + + pcp_ret_t pcp_point_cloud_alloc(pcp_point_cloud_t *pc, size_t size); + + pcp_ret_t pcp_point_cloud_load(pcp_point_cloud_t *pc, + const char *filename); + pcp_ret_t pcp_point_cloud_write(pcp_point_cloud_t *pc, + const char *filename, + int binary); + pcp_ret_t pcp_point_cloud_get_min(pcp_point_cloud_t *pc, + pcp_vec3f_t *min); + pcp_ret_t pcp_point_cloud_get_max(pcp_point_cloud_t *pc, + pcp_vec3f_t *max); + + pcp_ret_t pcp_point_cloud_tile(pcp_point_cloud_t *pc, + int n_x, + int n_y, + int n_z, + pcp_point_cloud_t **tiles); + + pcp_ret_t pcp_point_cloud_sample(pcp_point_cloud_t *pc, + float ratio, + unsigned char strategy, + pcp_point_cloud_t *out); + + pcp_ret_t + pcp_point_cloud_remove_dupplicates(pcp_point_cloud_t *pc, + pcp_point_cloud_t *out); + pcp_ret_t pcp_point_cloud_voxelize(pcp_point_cloud_t *pc, + float voxel_size, + pcp_point_cloud_t *out); + pcp_ret_t pcp_point_cloud_get_pixel_per_tile(pcp_point_cloud_t *pc, + int nx, + int ny, + int nz, + int width, + int height, + float *mvp, + int *pixel_count); +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/pcprep/pointcloud.h b/include/pcprep/pointcloud.h deleted file mode 100644 index 25073dc..0000000 --- a/include/pcprep/pointcloud.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef POINTCLOUD_H -#define POINTCLOUD_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "pcprep/pcprep_export.h" -#include "pcprep/vec3f.h" -#include -#include - - typedef struct pointcloud_t - { - float *pos; - uint8_t *rgb; - size_t size; // number of points, *pos have size*3 elements - } pointcloud_t; - // this need reference - PCPREP_EXPORT - int pointcloud_init(pointcloud_t *pc, size_t size); - // this need reference - PCPREP_EXPORT - int pointcloud_free(pointcloud_t *pc); - // this need reference - PCPREP_EXPORT - int pointcloud_load(pointcloud_t *pc, const char *filename); - // this doesn't need reference - PCPREP_EXPORT - int pointcloud_write(pointcloud_t pc, - const char *filename, - int binary); - // this doesn't need reference - PCPREP_EXPORT - int pointcloud_min(pointcloud_t pc, vec3f_t *min); - // this doesn't need reference - PCPREP_EXPORT - int pointcloud_max(pointcloud_t pc, vec3f_t *max); - PCPREP_EXPORT - int get_tile_id(vec3f_t n, vec3f_t min, vec3f_t max, vec3f_t v); - // this doesn't need reference - // `tiles` should be passed as a reference of a pointcloud_t* - PCPREP_EXPORT - int pointcloud_tile(pointcloud_t pc, - int n_x, - int n_y, - int n_z, - pointcloud_t **tiles); - // `pcs` should be passed as an array of pointcloud_t - // `output` should be passed as a reference to a pointcloud_t - PCPREP_EXPORT - int pointcloud_merge(pointcloud_t *pcs, - size_t pc_count, - pointcloud_t *out); - // `output` should be passed as a reference to a pointcloud_t - PCPREP_EXPORT - int pointcloud_sample(pointcloud_t pc, - float ratio, - unsigned char strategy, - pointcloud_t *out); - - static void pointcloud_element_merge(pointcloud_t pc, - int left, - int mid, - int right); - static void - pointcloud_element_merge_sort(pointcloud_t pc, int left, int right); - // `output` should be passed as a reference to a pointcloud_t - PCPREP_EXPORT - int pointcloud_remove_dupplicates(pointcloud_t pc, - pointcloud_t *out); - // `output` should be passed as a reference to a pointcloud_t - PCPREP_EXPORT - int pointcloud_voxel(pointcloud_t pc, - float voxel_size, - pointcloud_t *out); - PCPREP_EXPORT - int pointcloud_count_pixel_per_tile(pointcloud_t pc, - int nx, - int ny, - int nz, - int width, - int height, - float *mvp, - int *pixel_count); -#ifdef __cplusplus -} -#endif -#endif diff --git a/include/pcprep/core.h b/include/pcprep/utils.h similarity index 79% rename from include/pcprep/core.h rename to include/pcprep/utils.h index 8ad1043..52d7ab4 100644 --- a/include/pcprep/core.h +++ b/include/pcprep/utils.h @@ -1,5 +1,5 @@ -#ifndef CORE_H -#define CORE_H +#ifndef UTILS_H +#define UTILS_H #define PCP_SAMPLE_RULE_UNIFORM 0x00 #define PCP_FLOAT_ERROR 1e-6f @@ -8,7 +8,8 @@ #define HAVE_GPU #endif -#include "pcprep/pcprep_export.h" +#include + #include #include @@ -78,4 +79,18 @@ int save_viewport(unsigned char **row_pointers, int height, const char *filename); +// TODO: put this in utils.h +PCPREP_EXPORT +int get_tile_id(pcp_vec3f_t n, + pcp_vec3f_t min, + pcp_vec3f_t max, + pcp_vec3f_t v); +// `pcs` should be passed as an array of pcp_point_cloud_t +// `output` should be passed as a reference to a pcp_point_cloud_t +// TODO: put this in utils.h +PCPREP_EXPORT +int point_cloud_merge(pcp_point_cloud_t *pcs, + size_t pc_count, + pcp_point_cloud_t *out); + #endif diff --git a/include/pcprep/vec3f.h b/include/pcprep/vec3f.h index 6c50bd6..e82a5c3 100644 --- a/include/pcprep/vec3f.h +++ b/include/pcprep/vec3f.h @@ -4,82 +4,88 @@ extern "C" { #endif -#include "pcprep/core.h" +#include "pcprep/utils.h" #include - typedef struct vec3f_t + typedef struct pcp_vec3f_t { float x; float y; float z; - } vec3f_t; - static inline vec3f_t vec3f_set(float x, float y, float z) + } pcp_vec3f_t; + static inline pcp_vec3f_t pcp_vec3f_set(float x, float y, float z) { - vec3f_t v = {x, y, z}; + pcp_vec3f_t v = {x, y, z}; return v; } - static inline vec3f_t vec3f_int(vec3f_t v) + static inline pcp_vec3f_t pcp_vec3f_int(pcp_vec3f_t v) { - return (vec3f_t){ + return (pcp_vec3f_t){ (float)(int)v.x, (float)(int)v.y, (float)(int)v.z}; } - static inline vec3f_t vec3f_mul_scalar(vec3f_t v, float scalar) + static inline pcp_vec3f_t pcp_vec3f_mul_scalar(pcp_vec3f_t v, + float scalar) { - return (vec3f_t){v.x * scalar, v.y * scalar, v.z * scalar}; + return (pcp_vec3f_t){v.x * scalar, v.y * scalar, v.z * scalar}; } - static inline vec3f_t vec3f_inverse(vec3f_t v) + static inline pcp_vec3f_t pcp_vec3f_inverse(pcp_vec3f_t v) { - return (vec3f_t){1.0f / v.x, 1.0f / v.y, 1.0f / v.z}; + return (pcp_vec3f_t){1.0f / v.x, 1.0f / v.y, 1.0f / v.z}; } - static inline float vec3f_magnitude(vec3f_t v) + static inline float pcp_vec3f_magnitude(pcp_vec3f_t v) { return (float)sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } - static inline vec3f_t vec3f_normalize(vec3f_t v) + static inline pcp_vec3f_t pcp_vec3f_normalize(pcp_vec3f_t v) { - float mag = vec3f_magnitude(v); + float mag = pcp_vec3f_magnitude(v); if (mag > 0.0f) { - return vec3f_mul_scalar(v, 1.0f / mag); + return pcp_vec3f_mul_scalar(v, 1.0f / mag); } - return vec3f_set(0.0f, 0.0f, 0.0f); + return pcp_vec3f_set(0.0f, 0.0f, 0.0f); } - static inline vec3f_t vec3f_add(vec3f_t a, vec3f_t b) + static inline pcp_vec3f_t pcp_vec3f_add(pcp_vec3f_t a, + pcp_vec3f_t b) { - return (vec3f_t){a.x + b.x, a.y + b.y, a.z + b.z}; + return (pcp_vec3f_t){a.x + b.x, a.y + b.y, a.z + b.z}; } - static inline vec3f_t vec3f_sub(vec3f_t a, vec3f_t b) + static inline pcp_vec3f_t pcp_vec3f_sub(pcp_vec3f_t a, + pcp_vec3f_t b) { - return (vec3f_t){a.x - b.x, a.y - b.y, a.z - b.z}; + return (pcp_vec3f_t){a.x - b.x, a.y - b.y, a.z - b.z}; } - static inline vec3f_t vec3f_mul(vec3f_t a, vec3f_t b) + static inline pcp_vec3f_t pcp_vec3f_mul(pcp_vec3f_t a, + pcp_vec3f_t b) { - return (vec3f_t){a.x * b.x, a.y * b.y, a.z * b.z}; + return (pcp_vec3f_t){a.x * b.x, a.y * b.y, a.z * b.z}; } - static inline float vec3f_dot(vec3f_t a, vec3f_t b) + static inline float pcp_vec3f_dot(pcp_vec3f_t a, pcp_vec3f_t b) { return a.x * b.x + a.y * b.y + a.z * b.z; } - static inline vec3f_t vec3f_cross(vec3f_t a, vec3f_t b) + static inline pcp_vec3f_t pcp_vec3f_cross(pcp_vec3f_t a, + pcp_vec3f_t b) { - return (vec3f_t){a.y * b.z - a.z * b.y, - a.z * b.x - a.x * b.z, - a.x * b.y - a.y * b.x}; + return (pcp_vec3f_t){a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x}; } - static inline float vec3f_angle_between(vec3f_t a, vec3f_t b) + static inline float pcp_vec3f_angle_between(pcp_vec3f_t a, + pcp_vec3f_t b) { - float dot = vec3f_dot(a, b); - float magA = vec3f_magnitude(a); - float magB = vec3f_magnitude(b); + float dot = pcp_vec3f_dot(a, b); + float magA = pcp_vec3f_magnitude(a); + float magB = pcp_vec3f_magnitude(b); return (float)acos(dot / (magA * magB)); } - static inline int vec3f_eq(vec3f_t a, vec3f_t b) + static inline int pcp_vec3f_eq(pcp_vec3f_t a, pcp_vec3f_t b) { return float_equal(a.x, b.x) && float_equal(a.y, b.y) && float_equal(a.z, b.z); } - static inline int vec3f_g(vec3f_t a, vec3f_t b) + static inline int pcp_vec3f_g(pcp_vec3f_t a, pcp_vec3f_t b) { if (a.x < b.x) return 0; @@ -91,7 +97,7 @@ extern "C" return 1; return a.z > b.z; } - static inline int vec3f_l(vec3f_t a, vec3f_t b) + static inline int pcp_vec3f_l(pcp_vec3f_t a, pcp_vec3f_t b) { if (a.x < b.x) return 1; @@ -103,26 +109,28 @@ extern "C" return 0; return a.z < b.z; } - static inline int vec3f_geq(vec3f_t a, vec3f_t b) + static inline int pcp_vec3f_geq(pcp_vec3f_t a, pcp_vec3f_t b) { - return vec3f_g(a, b) || vec3f_eq(a, b); + return pcp_vec3f_g(a, b) || pcp_vec3f_eq(a, b); } - static inline int vec3f_leq(vec3f_t a, vec3f_t b) + static inline int pcp_vec3f_leq(pcp_vec3f_t a, pcp_vec3f_t b) { - return vec3f_l(a, b) || vec3f_eq(a, b); + return pcp_vec3f_l(a, b) || pcp_vec3f_eq(a, b); } - static inline vec3f_t vec3f_reflect(vec3f_t v, vec3f_t n) + static inline pcp_vec3f_t pcp_vec3f_reflect(pcp_vec3f_t v, + pcp_vec3f_t n) { - float dot = vec3f_dot(v, n); - return vec3f_sub(v, vec3f_mul_scalar(n, 2 * dot)); + float dot = pcp_vec3f_dot(v, n); + return pcp_vec3f_sub(v, pcp_vec3f_mul_scalar(n, 2 * dot)); } - static inline vec3f_t vec3f_quantize(vec3f_t v, float q) + static inline pcp_vec3f_t pcp_vec3f_quantize(pcp_vec3f_t v, float q) { - return (vec3f_t){ + return (pcp_vec3f_t){ quantize(v.x, q), quantize(v.y, q), quantize(v.z, q)}; } - static inline vec3f_t vec3f_mvp_mul(vec3f_t v, float *mvp) + static inline pcp_vec3f_t pcp_vec3f_mvp_mul(pcp_vec3f_t v, + float *mvp) { float temp_x = mvp[0] * v.x + mvp[4] * v.y + mvp[8] * v.z + mvp[12]; @@ -135,10 +143,10 @@ extern "C" temp_x /= temp_w; temp_y /= temp_w; temp_z /= temp_w; - return (vec3f_t){temp_x, temp_y, temp_z}; + return (pcp_vec3f_t){temp_x, temp_y, temp_z}; } - static inline vec3f_t - vec3f_rotate(vec3f_t v, float angle, vec3f_t axis) + static inline pcp_vec3f_t + pcp_vec3f_rotate(pcp_vec3f_t v, float angle, pcp_vec3f_t axis) { float c = cosf(angle); float s = sinf(angle); @@ -164,7 +172,7 @@ extern "C" uz * uz * one_minus_c + c } }; - vec3f_t result; + pcp_vec3f_t result; result.x = R[0][0] * v.x + R[0][1] * v.y + R[0][2] * v.z; result.y = R[1][0] * v.x + R[1][1] * v.y + R[1][2] * v.z; result.z = R[2][0] * v.x + R[2][1] * v.y + R[2][2] * v.z; diff --git a/include/pcprep/vec3u.h b/include/pcprep/vec3u.h index dd6256d..1e495d4 100644 --- a/include/pcprep/vec3u.h +++ b/include/pcprep/vec3u.h @@ -4,83 +4,90 @@ extern "C" { #endif -#include "pcprep/core.h" +#include "pcprep/utils.h" #include #include - typedef struct vec3u_t + typedef struct pcp_vec3u_t { uint32_t x; uint32_t y; uint32_t z; - } vec3u_t; + } pcp_vec3u_t; - static inline vec3u_t vec3u_set(uint32_t x, uint32_t y, uint32_t z) + static inline pcp_vec3u_t + pcp_vec3u_set(uint32_t x, uint32_t y, uint32_t z) { - vec3u_t v = {x, y, z}; + pcp_vec3u_t v = {x, y, z}; return v; } - static inline vec3u_t vec3u_mul_scalar(vec3u_t v, float scalar) + static inline pcp_vec3u_t pcp_vec3u_mul_scalar(pcp_vec3u_t v, + float scalar) { - return (vec3u_t){v.x * scalar, v.y * scalar, v.z * scalar}; + return (pcp_vec3u_t){v.x * scalar, v.y * scalar, v.z * scalar}; } - static inline float vec3u_magnitude(vec3u_t v) + static inline float pcp_vec3u_magnitude(pcp_vec3u_t v) { return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } - static inline vec3u_t vec3u_normalize(vec3u_t v) + static inline pcp_vec3u_t pcp_vec3u_normalize(pcp_vec3u_t v) { - float mag = vec3u_magnitude(v); + float mag = pcp_vec3u_magnitude(v); if (mag > 0.0f) { - return vec3u_mul_scalar(v, 1.0f / mag); + return pcp_vec3u_mul_scalar(v, 1.0f / mag); } - return vec3u_set(0.0f, 0.0f, 0.0f); + return pcp_vec3u_set(0.0f, 0.0f, 0.0f); } - static inline vec3u_t vec3u_add(vec3u_t a, vec3u_t b) + static inline pcp_vec3u_t pcp_vec3u_add(pcp_vec3u_t a, + pcp_vec3u_t b) { - return (vec3u_t){a.x + b.x, a.y + b.y, a.z + b.z}; + return (pcp_vec3u_t){a.x + b.x, a.y + b.y, a.z + b.z}; } - static inline vec3u_t vec3u_sub(vec3u_t a, vec3u_t b) + static inline pcp_vec3u_t pcp_vec3u_sub(pcp_vec3u_t a, + pcp_vec3u_t b) { - return (vec3u_t){a.x - b.x, a.y - b.y, a.z - b.z}; + return (pcp_vec3u_t){a.x - b.x, a.y - b.y, a.z - b.z}; } - static inline vec3u_t vec3u_mul(vec3u_t a, vec3u_t b) + static inline pcp_vec3u_t pcp_vec3u_mul(pcp_vec3u_t a, + pcp_vec3u_t b) { - return (vec3u_t){a.x * b.x, a.y * b.y, a.z * b.z}; + return (pcp_vec3u_t){a.x * b.x, a.y * b.y, a.z * b.z}; } - static inline float vec3u_dot(vec3u_t a, vec3u_t b) + static inline float pcp_vec3u_dot(pcp_vec3u_t a, pcp_vec3u_t b) { return a.x * b.x + a.y * b.y + a.z * b.z; } - static inline vec3u_t vec3u_cross(vec3u_t a, vec3u_t b) + static inline pcp_vec3u_t pcp_vec3u_cross(pcp_vec3u_t a, + pcp_vec3u_t b) { - return (vec3u_t){a.y * b.z - a.z * b.y, - a.z * b.x - a.x * b.z, - a.x * b.y - a.y * b.x}; + return (pcp_vec3u_t){a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x}; } - static inline float vec3u_angle_between(vec3u_t a, vec3u_t b) + static inline float pcp_vec3u_angle_between(pcp_vec3u_t a, + pcp_vec3u_t b) { - float dot = vec3u_dot(a, b); - float magA = vec3u_magnitude(a); - float magB = vec3u_magnitude(b); + float dot = pcp_vec3u_dot(a, b); + float magA = pcp_vec3u_magnitude(a); + float magB = pcp_vec3u_magnitude(b); return acos(dot / (magA * magB)); } - static inline int vec3u_eq(vec3u_t a, vec3u_t b) + static inline int pcp_vec3u_eq(pcp_vec3u_t a, pcp_vec3u_t b) { return a.x == b.x && a.y == b.y && a.z == b.z; } - static inline int vec3u_g(vec3u_t a, vec3u_t b) + static inline int pcp_vec3u_g(pcp_vec3u_t a, pcp_vec3u_t b) { if (a.x < b.x) return 0; @@ -93,7 +100,7 @@ extern "C" return a.z > b.z; } - static inline int vec3u_l(vec3u_t a, vec3u_t b) + static inline int pcp_vec3u_l(pcp_vec3u_t a, pcp_vec3u_t b) { if (a.x < b.x) return 1; @@ -106,25 +113,26 @@ extern "C" return a.z < b.z; } - static inline int vec3u_geq(vec3u_t a, vec3u_t b) + static inline int pcp_vec3u_geq(pcp_vec3u_t a, pcp_vec3u_t b) { - return vec3u_g(a, b) || vec3u_eq(a, b); + return pcp_vec3u_g(a, b) || pcp_vec3u_eq(a, b); } - static inline int vec3u_leq(vec3u_t a, vec3u_t b) + static inline int pcp_vec3u_leq(pcp_vec3u_t a, pcp_vec3u_t b) { - return vec3u_l(a, b) || vec3u_eq(a, b); + return pcp_vec3u_l(a, b) || pcp_vec3u_eq(a, b); } - static inline vec3u_t vec3u_reflect(vec3u_t v, vec3u_t n) + static inline pcp_vec3u_t pcp_vec3u_reflect(pcp_vec3u_t v, + pcp_vec3u_t n) { - float dot = vec3u_dot(v, n); - return vec3u_sub(v, vec3u_mul_scalar(n, 2 * dot)); + float dot = pcp_vec3u_dot(v, n); + return pcp_vec3u_sub(v, pcp_vec3u_mul_scalar(n, 2 * dot)); } - static inline vec3u_t vec3u_quantize(vec3u_t v, float q) + static inline pcp_vec3u_t pcp_vec3u_quantize(pcp_vec3u_t v, float q) { - return (vec3u_t){ + return (pcp_vec3u_t){ quantize(v.x, q), quantize(v.y, q), quantize(v.z, q)}; } diff --git a/include/pcprep/vec3uc.h b/include/pcprep/vec3uc.h index 12b09a5..f9c8ece 100644 --- a/include/pcprep/vec3uc.h +++ b/include/pcprep/vec3uc.h @@ -4,83 +4,90 @@ extern "C" { #endif -#include "pcprep/core.h" +#include "pcprep/utils.h" #include #include - typedef struct vec3uc_t + typedef struct pcp_vec3uc_t { uint8_t x; uint8_t y; uint8_t z; - } vec3uc_t; + } pcp_vec3uc_t; - static inline vec3uc_t vec3uc_set(uint8_t x, uint8_t y, uint8_t z) + static inline pcp_vec3uc_t + pcp_vec3uc_set(uint8_t x, uint8_t y, uint8_t z) { - vec3uc_t v = {x, y, z}; + pcp_vec3uc_t v = {x, y, z}; return v; } - static inline vec3uc_t vec3uc_mul_scalar(vec3uc_t v, float scalar) + static inline pcp_vec3uc_t pcp_vec3uc_mul_scalar(pcp_vec3uc_t v, + float scalar) { - return (vec3uc_t){v.x * scalar, v.y * scalar, v.z * scalar}; + return (pcp_vec3uc_t){v.x * scalar, v.y * scalar, v.z * scalar}; } - static inline float vec3uc_magnitude(vec3uc_t v) + static inline float pcp_vec3uc_magnitude(pcp_vec3uc_t v) { return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } - static inline vec3uc_t vec3uc_normalize(vec3uc_t v) + static inline pcp_vec3uc_t pcp_vec3uc_normalize(pcp_vec3uc_t v) { - float mag = vec3uc_magnitude(v); + float mag = pcp_vec3uc_magnitude(v); if (mag > 0.0f) { - return vec3uc_mul_scalar(v, 1.0f / mag); + return pcp_vec3uc_mul_scalar(v, 1.0f / mag); } - return vec3uc_set(0.0f, 0.0f, 0.0f); + return pcp_vec3uc_set(0.0f, 0.0f, 0.0f); } - static inline vec3uc_t vec3uc_add(vec3uc_t a, vec3uc_t b) + static inline pcp_vec3uc_t pcp_vec3uc_add(pcp_vec3uc_t a, + pcp_vec3uc_t b) { - return (vec3uc_t){a.x + b.x, a.y + b.y, a.z + b.z}; + return (pcp_vec3uc_t){a.x + b.x, a.y + b.y, a.z + b.z}; } - static inline vec3uc_t vec3uc_sub(vec3uc_t a, vec3uc_t b) + static inline pcp_vec3uc_t pcp_vec3uc_sub(pcp_vec3uc_t a, + pcp_vec3uc_t b) { - return (vec3uc_t){a.x - b.x, a.y - b.y, a.z - b.z}; + return (pcp_vec3uc_t){a.x - b.x, a.y - b.y, a.z - b.z}; } - static inline vec3uc_t vec3uc_mul(vec3uc_t a, vec3uc_t b) + static inline pcp_vec3uc_t pcp_vec3uc_mul(pcp_vec3uc_t a, + pcp_vec3uc_t b) { - return (vec3uc_t){a.x * b.x, a.y * b.y, a.z * b.z}; + return (pcp_vec3uc_t){a.x * b.x, a.y * b.y, a.z * b.z}; } - static inline float vec3uc_dot(vec3uc_t a, vec3uc_t b) + static inline float pcp_vec3uc_dot(pcp_vec3uc_t a, pcp_vec3uc_t b) { return a.x * b.x + a.y * b.y + a.z * b.z; } - static inline vec3uc_t vec3uc_cross(vec3uc_t a, vec3uc_t b) + static inline pcp_vec3uc_t pcp_vec3uc_cross(pcp_vec3uc_t a, + pcp_vec3uc_t b) { - return (vec3uc_t){a.y * b.z - a.z * b.y, - a.z * b.x - a.x * b.z, - a.x * b.y - a.y * b.x}; + return (pcp_vec3uc_t){a.y * b.z - a.z * b.y, + a.z * b.x - a.x * b.z, + a.x * b.y - a.y * b.x}; } - static inline float vec3uc_angle_between(vec3uc_t a, vec3uc_t b) + static inline float pcp_vec3uc_angle_between(pcp_vec3uc_t a, + pcp_vec3uc_t b) { - float dot = vec3uc_dot(a, b); - float magA = vec3uc_magnitude(a); - float magB = vec3uc_magnitude(b); + float dot = pcp_vec3uc_dot(a, b); + float magA = pcp_vec3uc_magnitude(a); + float magB = pcp_vec3uc_magnitude(b); return acos(dot / (magA * magB)); } - static inline int vec3uc_eq(vec3uc_t a, vec3uc_t b) + static inline int pcp_vec3uc_eq(pcp_vec3uc_t a, pcp_vec3uc_t b) { return a.x == b.x && a.y == b.y && a.z == b.z; } - static inline int vec3uc_g(vec3uc_t a, vec3uc_t b) + static inline int pcp_vec3uc_g(pcp_vec3uc_t a, pcp_vec3uc_t b) { if (a.x < b.x) return 0; @@ -93,7 +100,7 @@ extern "C" return a.z > b.z; } - static inline int vec3uc_l(vec3uc_t a, vec3uc_t b) + static inline int pcp_vec3uc_l(pcp_vec3uc_t a, pcp_vec3uc_t b) { if (a.x < b.x) return 1; @@ -106,25 +113,27 @@ extern "C" return a.z < b.z; } - static inline int vec3uc_geq(vec3uc_t a, vec3uc_t b) + static inline int pcp_vec3uc_geq(pcp_vec3uc_t a, pcp_vec3uc_t b) { - return vec3uc_g(a, b) || vec3uc_eq(a, b); + return pcp_vec3uc_g(a, b) || pcp_vec3uc_eq(a, b); } - static inline int vec3uc_leq(vec3uc_t a, vec3uc_t b) + static inline int pcp_vec3uc_leq(pcp_vec3uc_t a, pcp_vec3uc_t b) { - return vec3uc_l(a, b) || vec3uc_eq(a, b); + return pcp_vec3uc_l(a, b) || pcp_vec3uc_eq(a, b); } - static inline vec3uc_t vec3uc_reflect(vec3uc_t v, vec3uc_t n) + static inline pcp_vec3uc_t pcp_vec3uc_reflect(pcp_vec3uc_t v, + pcp_vec3uc_t n) { - float dot = vec3uc_dot(v, n); - return vec3uc_sub(v, vec3uc_mul_scalar(n, 2 * dot)); + float dot = pcp_vec3uc_dot(v, n); + return pcp_vec3uc_sub(v, pcp_vec3uc_mul_scalar(n, 2 * dot)); } - static inline vec3uc_t vec3uc_quantize(vec3uc_t v, float q) + static inline pcp_vec3uc_t pcp_vec3uc_quantize(pcp_vec3uc_t v, + float q) { - return (vec3uc_t){ + return (pcp_vec3uc_t){ quantize(v.x, q), quantize(v.y, q), quantize(v.z, q)}; } diff --git a/include/pcprep/wrapper.h b/include/pcprep/wrapper.h index 192faa3..2043768 100644 --- a/include/pcprep/wrapper.h +++ b/include/pcprep/wrapper.h @@ -14,9 +14,9 @@ extern "C" PCPREP_EXPORT int ply_count_face(const char *filename); PCPREP_EXPORT - int ply_pointcloud_loader(const char *filename, - float *pos, - unsigned char *rgb); + int ply_pcp_point_cloud_loader(const char *filename, + float *pos, + unsigned char *rgb); PCPREP_EXPORT int ply_mesh_loader(const char *filename, float *pos, int *indices); diff --git a/pcp/pcp.c b/pcp/pcp.c index 5e05717..19e5e6e 100644 --- a/pcp/pcp.c +++ b/pcp/pcp.c @@ -1,8 +1,8 @@ #include "pcp.h" #include #include -#include -#include +#include +#include #include #include #include @@ -11,40 +11,42 @@ int pcp_prepare(struct arguments *arg) { - pointcloud_t *in_pcs = NULL; - pointcloud_t *proc_pcs = NULL; - pointcloud_t *out_pcs = NULL; - char *input_path = NULL; - char *output_path = NULL; - char *output_tile_path = NULL; - char *input_tile_path = NULL; - int max_path_size = 0; - int binary = 0; - int proc_count = 0; - int in_count = 0; - int out_count = 0; - long long read_time = 0; - long long pre_proc_time = 0; - long long proc_time = 0; - long long post_proc_time = 0; - long long write_time = 0; - long long curr_time = 0; - - max_path_size = SIZE_PATH; - input_path = arg->input; - output_path = arg->output; - binary = arg->binary; + pcp_point_cloud_t *in_pcs = NULL; + pcp_point_cloud_t *proc_pcs = NULL; + pcp_point_cloud_t *out_pcs = NULL; + char *input_path = NULL; + char *output_path = NULL; + char *output_tile_path = NULL; + char *input_tile_path = NULL; + int max_path_size = 0; + int binary = 0; + int proc_count = 0; + int in_count = 0; + int out_count = 0; + long long read_time = 0; + long long pre_proc_time = 0; + long long proc_time = 0; + long long post_proc_time = 0; + long long write_time = 0; + long long curr_time = 0; + + max_path_size = SIZE_PATH; + input_path = arg->input; + output_path = arg->output; + binary = arg->binary; input_tile_path = (char *)malloc(max_path_size * sizeof(char)); output_tile_path = (char *)malloc(max_path_size * sizeof(char)); in_count = arg->tiled_input; curr_time = get_current_time_ms(); - in_pcs = (pointcloud_t *)calloc(in_count, sizeof(pointcloud_t)); + in_pcs = (pcp_point_cloud_t *)calloc(in_count, + sizeof(pcp_point_cloud_t)); for (int t = 0; t < in_count; t++) { + pcp_point_cloud_init(&in_pcs[t]); snprintf(input_tile_path, max_path_size, input_path, t); - pointcloud_load(&in_pcs[t], input_tile_path); + in_pcs[t].load(&in_pcs[t], input_tile_path); } read_time = get_current_time_ms() - curr_time; curr_time = get_current_time_ms(); @@ -57,17 +59,19 @@ int pcp_prepare(struct arguments *arg) nx = arg->tile.nx; ny = arg->tile.ny; nz = arg->tile.nz; - proc_count = pointcloud_tile(in_pcs[0], nx, ny, nz, &proc_pcs); + proc_count = nx * ny * nz; + in_pcs[0].tile(&in_pcs[0], nx, ny, nz, &proc_pcs); for (int i = 0; i < in_count; i++) - pointcloud_free(&in_pcs[i]); + pcp_point_cloud_free(&in_pcs[i]); free(in_pcs); } else if (in_count > 1 && arg->plan & PCP_PLAN_MERGE_NONE) { - proc_pcs = (pointcloud_t *)malloc(sizeof(pointcloud_t)); - proc_count = pointcloud_merge(in_pcs, in_count, &proc_pcs[0]); + proc_pcs = (pcp_point_cloud_t *)malloc(sizeof(pcp_point_cloud_t)); + pcp_point_cloud_init(proc_pcs); + proc_count = point_cloud_merge(in_pcs, in_count, &proc_pcs[0]); for (int i = 0; i < in_count; i++) - pointcloud_free(&in_pcs[i]); + pcp_point_cloud_free(&in_pcs[i]); free(in_pcs); } else @@ -197,7 +201,7 @@ int pcp_prepare(struct arguments *arg) .height = 0, .width = 0, .mvp_count = 0, - .background = (vec3uc_t){255, 255, 255} + .background = (pcp_vec3uc_t){255, 255, 255} }; param->mvp_count = json_parse_cam_matrix(curr->func_arg[0], @@ -241,10 +245,11 @@ int pcp_prepare(struct arguments *arg) if (arg->plan & PCP_PLAN_NONE_MERGE) { - out_pcs = (pointcloud_t *)malloc(sizeof(pointcloud_t)); - out_count = pointcloud_merge(proc_pcs, proc_count, &out_pcs[0]); + out_pcs = (pcp_point_cloud_t *)malloc(sizeof(pcp_point_cloud_t)); + pcp_point_cloud_init(out_pcs); + out_count = point_cloud_merge(proc_pcs, proc_count, &out_pcs[0]); for (int i = 0; i < proc_count; i++) - pointcloud_free(&proc_pcs[i]); + pcp_point_cloud_free(&proc_pcs[i]); free(proc_pcs); } else if (arg->plan & PCP_PLAN_NONE_TILE) @@ -255,9 +260,10 @@ int pcp_prepare(struct arguments *arg) nx = arg->tile.nx; ny = arg->tile.ny; nz = arg->tile.nz; - out_count = pointcloud_tile(proc_pcs[0], nx, ny, nz, &out_pcs); + out_count = nx * ny * nz; + proc_pcs[0].tile(&proc_pcs[0], nx, ny, nz, &out_pcs); for (int i = 0; i < proc_count; i++) - pointcloud_free(&proc_pcs[i]); + pcp_point_cloud_free(&proc_pcs[i]); free(proc_pcs); } else @@ -279,7 +285,7 @@ int pcp_prepare(struct arguments *arg) printf("Tile %d have no points, skip writing...\n", t); } snprintf(output_tile_path, max_path_size, output_path, t); - pointcloud_write(out_pcs[t], output_tile_path, binary); + out_pcs[t].write(&out_pcs[t], output_tile_path, binary); } write_time = get_current_time_ms() - curr_time; @@ -294,7 +300,7 @@ int pcp_prepare(struct arguments *arg) write_time); for (int i = 0; i < out_count; i++) - pointcloud_free(&out_pcs[i]); + pcp_point_cloud_free(&out_pcs[i]); free(out_pcs); free(input_tile_path); diff --git a/pcp/pcp.h b/pcp/pcp.h index 7fd91fd..11c7b3c 100644 --- a/pcp/pcp.h +++ b/pcp/pcp.h @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -114,9 +114,9 @@ const func_info_t *find_func(const char *name, return NULL; } -typedef unsigned int (*func_f)(pointcloud_t *pc, - void *arg, - int pc_id); +typedef unsigned int (*func_f)(pcp_point_cloud_t *pc, + void *arg, + int pc_id); func_f pcp_process_legs_g[MAX_PROCESS] = {NULL}; void *pcp_process_params_g[MAX_PROCESS] = {NULL}; unsigned int pcp_process_legs_count_g = 0; @@ -139,7 +139,7 @@ unsigned int pcp_status_legs_append(func_f func, void *param) return 1; } -unsigned int pcp_process_legs_run(pointcloud_t *pc, int pc_id) +unsigned int pcp_process_legs_run(pcp_point_cloud_t *pc, int pc_id) { for (int i = 0; i < pcp_process_legs_count_g; i++) { @@ -149,7 +149,7 @@ unsigned int pcp_process_legs_run(pointcloud_t *pc, int pc_id) } } } -unsigned int pcp_status_legs_run(pointcloud_t *pc, int pc_id) +unsigned int pcp_status_legs_run(pcp_point_cloud_t *pc, int pc_id) { for (int i = 0; i < pcp_status_legs_count_g; i++) { @@ -174,34 +174,37 @@ typedef struct pcp_sample_p_arg_t unsigned char strategy; } pcp_sample_p_arg_t; -unsigned int pcp_sample_p(pointcloud_t *pc, void *arg, int pc_id) +unsigned int pcp_sample_p(pcp_point_cloud_t *pc, void *arg, int pc_id) { pcp_sample_p_arg_t *param = (pcp_sample_p_arg_t *)arg; - pointcloud_t out = {NULL, NULL, 0}; - pointcloud_sample(*pc, param->ratio, param->strategy, &out); - pointcloud_free(pc); + pcp_point_cloud_t out = {0}; + pcp_point_cloud_init(&out); + pc->sample(pc, param->ratio, param->strategy, &out); + pcp_point_cloud_free(pc); *pc = out; return 1; } -unsigned int pcp_voxel_p(pointcloud_t *pc, void *arg, int pc_id) +unsigned int pcp_voxel_p(pcp_point_cloud_t *pc, void *arg, int pc_id) { - float step_size = *(float *)arg; + float step_size = *(float *)arg; - pointcloud_t out = {NULL, NULL, 0}; - pointcloud_voxel(*pc, step_size, &out); - pointcloud_free(pc); + pcp_point_cloud_t out = {0}; + pcp_point_cloud_init(&out); + pc->voxelize(pc, step_size, &out); + pcp_point_cloud_free(pc); *pc = out; return 1; } unsigned int -pcp_remove_dupplicates_p(pointcloud_t *pc, void *arg, int pc_id) +pcp_remove_dupplicates_p(pcp_point_cloud_t *pc, void *arg, int pc_id) { - pointcloud_t out = {NULL, NULL, 0}; - pointcloud_remove_dupplicates(*pc, &out); - pointcloud_free(pc); + pcp_point_cloud_t out = {0}; + pcp_point_cloud_init(&out); + pc->remove_dupplicates(pc, &out); + pcp_point_cloud_free(pc); *pc = out; return 1; } @@ -213,13 +216,14 @@ typedef struct pcp_aabb_s_arg_t char output_path[SIZE_PATH]; } pcp_aabb_s_arg_t; -unsigned int pcp_aabb_s(pointcloud_t *pc, void *arg, int pc_id) +unsigned int pcp_aabb_s(pcp_point_cloud_t *pc, void *arg, int pc_id) { pcp_aabb_s_arg_t *param = (pcp_aabb_s_arg_t *)arg; - vec3f_t min, max; - pointcloud_min(*pc, &min); - pointcloud_max(*pc, &max); + pcp_vec3f_t min = {0}; + pcp_vec3f_t max = {0}; + pc->get_min(pc, &min); + pc->get_max(pc, &max); if (param->output == 0 || param->output == 2) { printf("Min: %f %f %f\n", min.x, min.y, min.z); @@ -229,46 +233,54 @@ unsigned int pcp_aabb_s(pointcloud_t *pc, void *arg, int pc_id) return 1; } } - aabb_t aabb = {min, max}; - mesh_t mesh = {0}; - aabb_to_mesh(aabb, &mesh); + pcp_aabb_t aabb = {0}; + pcp_mesh_t mesh = {0}; + char tile_path[SIZE_PATH] = {0}; + + pcp_mesh_init(&mesh); + pcp_aabb_init(&aabb); + + aabb.min = min; + aabb.max = max; + + aabb.to_mesh(&aabb, &mesh); - char tile_path[SIZE_PATH]; snprintf(tile_path, SIZE_PATH, param->output_path, pc_id); - mesh_write(mesh, tile_path, param->binary); - mesh_free(&mesh); + mesh.write(&mesh, tile_path, param->binary); + pcp_mesh_free(&mesh); + pcp_aabb_free(&aabb); return 1; } #ifdef PCP_STAT_SAVE_VIEWPORT typedef struct pcp_save_viewport_s_arg_t { - char outpath[SIZE_PATH]; - float mvps[MAX_MVP_COUNT][4][4]; // 4x4 matrixes - int mvp_count; - size_t width; - size_t height; - vec3uc_t background; + char outpath[SIZE_PATH]; + float mvps[MAX_MVP_COUNT][4][4]; // 4x4 matrixes + int mvp_count; + size_t width; + size_t height; + pcp_vec3uc_t background; } pcp_save_viewport_s_arg_t; unsigned int -pcp_save_viewport_s(pointcloud_t *pc, void *arg, int pc_id) +pcp_save_viewport_s(pcp_point_cloud_t *pc, void *arg, int pc_id) { pcp_save_viewport_s_arg_t *param = (pcp_save_viewport_s_arg_t *)arg; - canvas_t cv = {0}; + pcp_canvas_t cv = {0}; - canvas_init(&cv, - param->width, - param->height, + pcp_canvas_init(&cv, + param->width, + param->height, #ifdef HAVE_GPU - NULL, - NULL, + NULL, + NULL, #endif - param->background); + param->background); for (int v = 0; v < param->mvp_count; v++) { - canvas_clear(&cv); + cv.clear(&cv); cv.draw_points( &cv, ¶m->mvps[v][0][0], pc->pos, pc->rgb, pc->size); @@ -288,7 +300,7 @@ pcp_save_viewport_s(pointcloud_t *pc, void *arg, int pc_id) free(row_pointers[i]); free(row_pointers); } - canvas_free(&cv); + pcp_canvas_free(&cv); return 1; } #endif @@ -306,7 +318,7 @@ typedef struct pcp_pixel_per_tile_s_arg_t } pcp_pixel_per_tile_s_arg_t; unsigned int -pcp_pixel_per_tile_s(pointcloud_t *pc, void *arg, int pc_id) +pcp_pixel_per_tile_s(pcp_point_cloud_t *pc, void *arg, int pc_id) { pcp_pixel_per_tile_s_arg_t *param = (pcp_pixel_per_tile_s_arg_t *)arg; @@ -318,14 +330,14 @@ pcp_pixel_per_tile_s(pointcloud_t *pc, void *arg, int pc_id) for (int v = 0; v < param->mvp_count; v++) { - pointcloud_count_pixel_per_tile(*pc, - param->nx, - param->ny, - param->nz, - param->width, - param->height, - ¶m->mvps[v][0][0], - &pixel_count[v][0]); + pc->get_pixel_per_tile(pc, + param->nx, + param->ny, + param->nz, + param->width, + param->height, + ¶m->mvps[v][0][0], + &pixel_count[v][0]); } json_write_tiles_pixel(param->outpath, num_tile, @@ -347,28 +359,35 @@ typedef struct pcp_screen_area_estimation_s_arg_t char outpath[SIZE_PATH]; } pcp_screen_area_estimation_s_arg_t; -unsigned int -pcp_screen_area_estimation_s(pointcloud_t *pc, void *arg, int pc_id) +unsigned int pcp_screen_area_estimation_s(pcp_point_cloud_t *pc, + void *arg, + int pc_id) { float *screen_ratio = NULL; + pcp_vec3f_t min = {0}; + pcp_vec3f_t max = {0}; + pcp_aabb_t aabb = {0}; + pcp_mesh_t aabb_m = {0}; + pcp_screen_area_estimation_s_arg_t *param = (pcp_screen_area_estimation_s_arg_t *)arg; - vec3f_t min, max; - pointcloud_min(*pc, &min); - pointcloud_max(*pc, &max); + pc->get_min(pc, &min); + pc->get_max(pc, &max); + + pcp_aabb_init(&aabb); + pcp_mesh_init(&aabb_m); - aabb_t aabb = {.min = min, .max = max}; - mesh_t aabb_m = { - .indices = NULL, .num_indices = 0, .num_verts = 0, .pos = NULL}; + aabb.min = min; + aabb.max = max; - aabb_to_mesh(aabb, &aabb_m); + aabb.to_mesh(&aabb, &aabb_m); screen_ratio = (float *)malloc(sizeof(float) * param->mvp_count); for (int v = 0; v < param->mvp_count; v++) { - mesh_screen_ratio( - aabb_m, ¶m->mvps[v][0][0], &screen_ratio[v]); + aabb_m.get_screen_ratio( + &aabb_m, ¶m->mvps[v][0][0], &screen_ratio[v]); } char pc_path[SIZE_PATH]; snprintf(pc_path, SIZE_PATH, param->outpath, pc_id); @@ -378,5 +397,6 @@ pcp_screen_area_estimation_s(pointcloud_t *pc, void *arg, int pc_id) param->height, screen_ratio); free(screen_ratio); - mesh_free(&aabb_m); + pcp_mesh_free(&aabb_m); + pcp_aabb_free(&aabb); } diff --git a/source/aabb.c b/source/aabb.c index 53772a8..55429b6 100644 --- a/source/aabb.c +++ b/source/aabb.c @@ -1,39 +1,56 @@ #include #include -int aabb_to_mesh(aabb_t aabb, mesh_t *mesh) +pcp_ret_t pcp_aabb_init(pcp_aabb_t *self) +{ + *self = (pcp_aabb_t){0}; + self->to_mesh = pcp_aabb_to_mesh; + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_aabb_free(pcp_aabb_t *self) +{ + *self = (pcp_aabb_t){0}; + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_aabb_to_mesh(pcp_aabb_t *self, pcp_mesh_t *mesh) { // Check if the AABB is valid - if (aabb.min.x > aabb.max.x || aabb.min.y > aabb.max.y || - aabb.min.z > aabb.max.z) + if (self->min.x > self->max.x || self->min.y > self->max.y || + self->min.z > self->max.z) { - return -1; + return PCPREP_RET_FAIL; } - mesh_init(mesh, 8, 12 * 3); - - vec3f_t *vertices = (vec3f_t *)mesh->pos; - - vertices[0] = aabb.min; - vertices[1] = vec3f_set(aabb.min.x, aabb.min.y, aabb.max.z); - vertices[2] = vec3f_set(aabb.min.x, aabb.max.y, aabb.min.z); - vertices[3] = vec3f_set(aabb.min.x, aabb.max.y, aabb.max.z); - vertices[4] = vec3f_set(aabb.max.x, aabb.min.y, aabb.min.z); - vertices[5] = vec3f_set(aabb.max.x, aabb.min.y, aabb.max.z); - vertices[6] = vec3f_set(aabb.max.x, aabb.max.y, aabb.min.z); - vertices[7] = aabb.max; - - vec3u_t *faces = (vec3u_t *)mesh->indices; - faces[0] = vec3u_set(0, 1, 3); - faces[1] = vec3u_set(0, 3, 2); - faces[2] = vec3u_set(4, 7, 5); - faces[3] = vec3u_set(4, 6, 7); - faces[4] = vec3u_set(0, 6, 4); - faces[5] = vec3u_set(0, 2, 6); - faces[6] = vec3u_set(1, 5, 7); - faces[7] = vec3u_set(1, 7, 3); - faces[8] = vec3u_set(0, 5, 1); - faces[9] = vec3u_set(0, 4, 5); - faces[10] = vec3u_set(2, 3, 7); - faces[11] = vec3u_set(2, 7, 6); - return 0; + + pcp_vec3f_t *vertices = PCPREP_NULL; + pcp_vec3u_t *faces = PCPREP_NULL; + + mesh->alloc(mesh, 8, 12 * 3); + + vertices = (pcp_vec3f_t *)mesh->pos; + + vertices[0] = self->min; + vertices[1] = pcp_vec3f_set(self->min.x, self->min.y, self->max.z); + vertices[2] = pcp_vec3f_set(self->min.x, self->max.y, self->min.z); + vertices[3] = pcp_vec3f_set(self->min.x, self->max.y, self->max.z); + vertices[4] = pcp_vec3f_set(self->max.x, self->min.y, self->min.z); + vertices[5] = pcp_vec3f_set(self->max.x, self->min.y, self->max.z); + vertices[6] = pcp_vec3f_set(self->max.x, self->max.y, self->min.z); + vertices[7] = self->max; + + faces = (pcp_vec3u_t *)mesh->indices; + faces[0] = pcp_vec3u_set(0, 1, 3); + faces[1] = pcp_vec3u_set(0, 3, 2); + faces[2] = pcp_vec3u_set(4, 7, 5); + faces[3] = pcp_vec3u_set(4, 6, 7); + faces[4] = pcp_vec3u_set(0, 6, 4); + faces[5] = pcp_vec3u_set(0, 2, 6); + faces[6] = pcp_vec3u_set(1, 5, 7); + faces[7] = pcp_vec3u_set(1, 7, 3); + faces[8] = pcp_vec3u_set(0, 5, 1); + faces[9] = pcp_vec3u_set(0, 4, 5); + faces[10] = pcp_vec3u_set(2, 3, 7); + faces[11] = pcp_vec3u_set(2, 7, 6); + return PCPREP_RET_SUCCESS; } diff --git a/source/canvas.c b/source/canvas.c index e3b0061..b709914 100644 --- a/source/canvas.c +++ b/source/canvas.c @@ -5,8 +5,8 @@ #include #include #ifdef HAVE_GPU -#include #include +#include #include static const char *default_vert_shader = @@ -35,11 +35,11 @@ GLuint load_shader(char *vertex_shader_code, GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); - if (vertex_shader_code == NULL) + if (vertex_shader_code == PCPREP_NULL) { vertex_shader_code = (char *)default_vert_shader; } - if (fragment_shader_code == NULL) + if (fragment_shader_code == PCPREP_NULL) { fragment_shader_code = (char *)default_frag_shader; } @@ -49,7 +49,8 @@ GLuint load_shader(char *vertex_shader_code, // Compile Vertex Shader const char *VertexSourcePointer = vertex_shader_code; - glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); + glShaderSource( + VertexShaderID, 1, &VertexSourcePointer, PCPREP_NULL); glCompileShader(VertexShaderID); // Check Vertex Shader @@ -61,7 +62,7 @@ GLuint load_shader(char *vertex_shader_code, (char *)malloc(InfoLogLength + 1); glGetShaderInfoLog(VertexShaderID, InfoLogLength, - NULL, + PCPREP_NULL, VertexShaderErrorMessage); fprintf(stderr, "%s\n", VertexShaderErrorMessage); free(VertexShaderErrorMessage); @@ -69,7 +70,8 @@ GLuint load_shader(char *vertex_shader_code, // Compile Fragment Shader const char *FragmentSourcePointer = fragment_shader_code; - glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); + glShaderSource( + FragmentShaderID, 1, &FragmentSourcePointer, PCPREP_NULL); glCompileShader(FragmentShaderID); // Check Fragment Shader @@ -81,7 +83,7 @@ GLuint load_shader(char *vertex_shader_code, (char *)malloc(InfoLogLength + 1); glGetShaderInfoLog(FragmentShaderID, InfoLogLength, - NULL, + PCPREP_NULL, FragmentShaderErrorMessage); fprintf(stderr, "%s\n", FragmentShaderErrorMessage); free(FragmentShaderErrorMessage); @@ -100,7 +102,7 @@ GLuint load_shader(char *vertex_shader_code, { char *ProgramErrorMessage = (char *)malloc(InfoLogLength + 1); glGetProgramInfoLog( - ProgramID, InfoLogLength, NULL, ProgramErrorMessage); + ProgramID, InfoLogLength, PCPREP_NULL, ProgramErrorMessage); fprintf(stderr, "%s\n", ProgramErrorMessage); free(ProgramErrorMessage); } @@ -114,9 +116,9 @@ GLuint load_shader(char *vertex_shader_code, return ProgramID; } -static int canvas_init_gl(canvas_t *cv) +static pcs_ret_t pcp_canvas_start_gl(pcp_canvas_t *cv) { - GLFWwindow *window = NULL; + GLFWwindow *window = PCPREP_NULL; cv->vertex_array_id = 0; cv->program_id = 0; @@ -127,7 +129,7 @@ static int canvas_init_gl(canvas_t *cv) if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW\n"); - return -1; + return PCPREP_RET_FAIL; } glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); @@ -135,12 +137,12 @@ static int canvas_init_gl(canvas_t *cv) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); - window = glfwCreateWindow(1, 1, "Hidden", NULL, NULL); + window = glfwCreateWindow(1, 1, "Hidden", PCPREP_NULL, PCPREP_NULL); if (!window) { fprintf(stderr, "Failed to open GLFW window.\n"); glfwTerminate(); - return -1; + return PCPREP_RET_FAIL; } glfwMakeContextCurrent(window); @@ -149,7 +151,7 @@ static int canvas_init_gl(canvas_t *cv) { fprintf(stderr, "Failed to initialize GLEW\n"); glfwTerminate(); - return -1; + return PCPREP_RET_FAIL; } glClearColor(cv->bg_col.x / 255.0f, @@ -181,7 +183,7 @@ static int canvas_init_gl(canvas_t *cv) 0, GL_RGB, GL_UNSIGNED_BYTE, - NULL); + PCPREP_NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -208,12 +210,12 @@ static int canvas_init_gl(canvas_t *cv) GL_FRAMEBUFFER_COMPLETE) { fprintf(stderr, "Framebuffer is not complete!\n"); - return -1; + return PCPREP_RET_FAIL; } - return 0; + return PCPREP_RET_SUCESS; } -int canvas_free_gl(canvas_t *cv) +pcp_ret_t pcp_canvas_free_gl(pcp_canvas_t *cv) { glDeleteFramebuffers(1, &cv->frame_buffer); glDeleteTextures(1, &cv->rendered_texture); @@ -227,19 +229,19 @@ int canvas_free_gl(canvas_t *cv) glfwTerminate(); - return 0; + return PCPREP_RET_SUCCESS; } #endif -int canvas_init(canvas_t *cv, - size_t width, - size_t height, +pcp_ret_t pcp_canvas_init(pcp_canvas_t *cv, + size_t width, + size_t height, #ifdef HAVE_GPU - char *vert_shader, - char *frag_shader, + char *vert_shader, + char *frag_shader, #endif - vec3uc_t bg_col) + pcp_vec3uc_t bg_col) { cv->width = width; cv->height = height; @@ -254,18 +256,19 @@ int canvas_init(canvas_t *cv, #ifdef HAVE_GPU cv->vert_shader = vert_shader; cv->frag_shader = frag_shader; - canvas_init_gl(cv); - cv->draw_points = canvas_draw_points_gpu; + pcp_canvas_start_gl(cv); + cv->draw_points = pcp_canvas_draw_points_gpu; #else - cv->draw_points = canvas_draw_points_cpu; + cv->draw_points = pcp_canvas_draw_points_cpu; #endif - cv->clear = canvas_clear; + cv->clear = pcp_canvas_clear; + return PCPREP_RET_SUCCESS; } -int canvas_free(canvas_t *cv) +pcp_ret_t pcp_canvas_free(pcp_canvas_t *cv) { - cv->bg_col = (vec3uc_t){0}; + cv->bg_col = (pcp_vec3uc_t){0}; if (cv->pixels) { free(cv->pixels); @@ -290,15 +293,17 @@ int canvas_free(canvas_t *cv) #ifdef HAVE_GPU cv->vert_shader = 0; cv->frag_shader = 0; - canvas_free_gl(cv); + pcp_canvas_free_gl(cv); #endif + + return PCPREP_RET_SUCCESS; } #ifdef HAVE_GPU -void canvas_draw_points_gpu(canvas_t *cv, - float *mvp, - float *pos, - unsigned char *rgb, - size_t count) +pcp_ret_t pcp_canvas_draw_points_gpu(pcp_canvas_t *cv, + float *mvp, + float *pos, + unsigned char *rgb, + size_t count) { unsigned int vbuffer = 0; unsigned int rbuffer = 0; @@ -323,11 +328,12 @@ void canvas_draw_points_gpu(canvas_t *cv, glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vbuffer); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, PCPREP_NULL); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, rbuffer); - glVertexAttribPointer(1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL); + glVertexAttribPointer( + 1, 3, GL_UNSIGNED_BYTE, GL_TRUE, 0, PCPREP_NULL); glBindFramebuffer(GL_FRAMEBUFFER, cv->frame_buffer); glViewport(0, 0, cv->width, cv->height); @@ -348,22 +354,24 @@ void canvas_draw_points_gpu(canvas_t *cv, glDeleteBuffers(1, &rbuffer); glDeleteBuffers(1, &vbuffer); + + return PCPREP_RET_SUCCESS; } #endif -void canvas_draw_points_cpu(canvas_t *cv, - float *mvp, - float *pos, - unsigned char *rgb, - size_t count) +pcp_ret_t pcp_canvas_draw_points_cpu(pcp_canvas_t *cv, + float *mvp, + float *pos, + unsigned char *rgb, + size_t count) { - vec3f_t *positions = NULL; - vec3uc_t *colors = NULL; - vec3uc_t *rgb_pixels = NULL; - size_t screen_w = 0; - size_t screen_h = 0; + pcp_vec3f_t *positions = PCPREP_NULL; + pcp_vec3uc_t *colors = PCPREP_NULL; + pcp_vec3uc_t *rgb_pixels = PCPREP_NULL; + size_t screen_w = 0; + size_t screen_h = 0; - rgb_pixels = (vec3uc_t *)cv->pixels; + rgb_pixels = (pcp_vec3uc_t *)cv->pixels; for (int i = 0; i < cv->height; i++) { @@ -374,12 +382,12 @@ void canvas_draw_points_cpu(canvas_t *cv, } } - positions = (vec3f_t *)pos; - colors = (vec3uc_t *)rgb; + positions = (pcp_vec3f_t *)pos; + colors = (pcp_vec3uc_t *)rgb; for (int i = 0; i < count; i++) { - vec3f_t ndc = vec3f_mvp_mul(positions[i], mvp); + pcp_vec3f_t ndc = pcp_vec3f_mvp_mul(positions[i], mvp); if (ndc.x >= -1 && ndc.x <= 1 && ndc.y >= -1 && ndc.y <= 1 && ndc.z >= 0 && ndc.z <= 1) { @@ -399,9 +407,10 @@ void canvas_draw_points_cpu(canvas_t *cv, } } } + return PCPREP_RET_SUCCESS; } -void canvas_clear(canvas_t *cv) +pcp_ret_t pcp_canvas_clear(pcp_canvas_t *cv) { memset(cv->pixels, 0, @@ -410,4 +419,5 @@ void canvas_clear(canvas_t *cv) { memset(cv->min_z_value[i], 0, sizeof(float) * cv->width); } + return PCPREP_RET_SUCCESS; } diff --git a/source/mesh.c b/source/mesh.c index 8b4dc06..e1a71a9 100644 --- a/source/mesh.c +++ b/source/mesh.c @@ -1,64 +1,85 @@ -#include #include +#include #include #include #define MSH_PLY_INCLUDE_LIBC_HEADERS #define MSH_PLY_IMPLEMENTATION #include -int mesh_init(mesh_t *mesh, uint32_t num_verts, uint32_t num_indices) +pcp_ret_t pcp_mesh_init(pcp_mesh_t *self) +{ + *self = (pcp_mesh_t){0}; + self->alloc = pcp_mesh_alloc; + self->load = pcp_mesh_load; + self->write = pcp_mesh_write; + self->get_screen_ratio = pcp_mesh_get_screen_ratio; + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_mesh_alloc(pcp_mesh_t *self, + uint32_t num_verts, + uint32_t num_indices) { if (num_verts < 0 || num_indices < 0) - return -1; - mesh->pos = (float *)malloc(sizeof(float) * 3 * num_verts); - mesh->num_verts = num_verts; + { + return PCPREP_RET_FAIL; + } + self->pos = (float *)malloc(sizeof(float) * 3 * num_verts); + self->num_verts = num_verts; - mesh->indices = (uint32_t *)malloc(sizeof(uint32_t) * num_indices); - mesh->num_indices = num_indices; - return 1; + self->indices = (uint32_t *)malloc(sizeof(uint32_t) * num_indices); + self->num_indices = num_indices; + return PCPREP_RET_SUCCESS; } -int mesh_free(mesh_t *mesh) +pcp_ret_t pcp_mesh_free(pcp_mesh_t *self) { - if (mesh == NULL) - return 1; - if (mesh->pos) + if (self == NULL) { - free(mesh->pos); - mesh->pos = NULL; + return PCPREP_RET_FAIL; } - if (mesh->indices) + if (self->pos) { - free(mesh->indices); - mesh->indices = NULL; + free(self->pos); + self->pos = NULL; } - return 1; + if (self->indices) + { + free(self->indices); + self->indices = NULL; + } + return PCPREP_RET_SUCCESS; } -int mesh_load(mesh_t *mesh, const char *filename) +pcp_ret_t pcp_mesh_load(pcp_mesh_t *self, const char *filename) { - mesh_init( - mesh, ply_count_vertex(filename), ply_count_face(filename) * 3); - return ply_mesh_loader(filename, mesh->pos, mesh->indices); + self->alloc( + self, ply_count_vertex(filename), ply_count_face(filename) * 3); + if (!ply_mesh_loader(filename, self->pos, self->indices)) + { + return PCPREP_RET_FAIL; + } + return PCPREP_RET_SUCCESS; } -int mesh_write(mesh_t mesh, const char *filename, int binary) +pcp_ret_t +pcp_mesh_write(pcp_mesh_t *self, const char *filename, int binary) { - msh_ply_desc_t descriptors[2]; - descriptors[0] = (msh_ply_desc_t){ - .element_name = "vertex", - .property_names = (const char *[]){"x", "y", "z"}, - .num_properties = 3, - .data_type = MSH_PLY_FLOAT, - .data = &mesh.pos, - .data_count = &mesh.num_verts + msh_ply_desc_t descriptors[2] = {0}; + descriptors[0] = (msh_ply_desc_t){ + .element_name = "vertex", + .property_names = (const char *[]){"x", "y", "z"}, + .num_properties = 3, + .data_type = MSH_PLY_FLOAT, + .data = &(self->pos), + .data_count = &(self->num_verts) }; - uint32_t num_faces = mesh.num_indices / 3; + uint32_t num_faces = self->num_indices / 3; descriptors[1] = (msh_ply_desc_t){ .element_name = "face", .property_names = (const char *[]){"vertex_indices"}, .num_properties = 1, .data_type = MSH_PLY_INT32, .list_type = MSH_PLY_UINT8, - .data = &mesh.indices, + .data = &(self->indices), .data_count = &num_faces, .list_size_hint = 3}; @@ -71,6 +92,7 @@ int mesh_write(mesh_t mesh, const char *filename, int binary) msh_ply_write(pf); } msh_ply_close(pf); + return PCPREP_RET_SUCCESS; } static int is_toward(vec2f_t a, vec2f_t b, vec2f_t c) @@ -78,22 +100,27 @@ static int is_toward(vec2f_t a, vec2f_t b, vec2f_t c) return (b.x - a.x) * (c.y - a.y) > (c.x - a.x) * (b.y - a.y); } -int mesh_screen_ratio(mesh_t mesh, float *mvp, float *screen_ratio) +pcp_ret_t pcp_mesh_get_screen_ratio(pcp_mesh_t *self, + float *mvp, + float *screen_ratio) { - *screen_ratio = 0; + pcp_vec3f_t *vertices = PCPREP_NULL; + pcp_vec3f_t *ndcs = PCPREP_NULL; + + *screen_ratio = 0; - vec3f_t *vertices = (vec3f_t *)mesh.pos; - vec3f_t *ndcs = (vec3f_t *)malloc(sizeof(vec3f_t) * mesh.num_verts); - for (int i = 0; i < mesh.num_verts; i++) + vertices = (pcp_vec3f_t *)self->pos; + ndcs = (pcp_vec3f_t *)malloc(sizeof(pcp_vec3f_t) * self->num_verts); + for (int i = 0; i < self->num_verts; i++) { - ndcs[i] = vec3f_mvp_mul(vertices[i], mvp); + ndcs[i] = pcp_vec3f_mvp_mul(vertices[i], mvp); } - for (int i = 0; i < mesh.num_indices / 3; i++) + for (int i = 0; i < self->num_indices / 3; i++) { - int idx0 = mesh.indices[i * 3]; - int idx1 = mesh.indices[i * 3 + 1]; - int idx2 = mesh.indices[i * 3 + 2]; + int idx0 = self->indices[i * 3]; + int idx1 = self->indices[i * 3 + 1]; + int idx2 = self->indices[i * 3 + 2]; if (ndcs[idx0].z >= 0 && ndcs[idx0].z <= 1 && ndcs[idx1].z >= 0 && ndcs[idx1].z <= 1 && ndcs[idx2].z >= 0 && ndcs[idx2].z <= 1 && is_toward((vec2f_t){ndcs[idx0].x, ndcs[idx0].y}, @@ -109,4 +136,5 @@ int mesh_screen_ratio(mesh_t mesh, float *mvp, float *screen_ratio) // since the screen in ndc is a 2 x 2 square *screen_ratio /= 4; free(ndcs); + return PCPREP_RET_SUCCESS; } diff --git a/source/point_cloud.c b/source/point_cloud.c new file mode 100644 index 0000000..848be7e --- /dev/null +++ b/source/point_cloud.c @@ -0,0 +1,495 @@ +#include "pcprep/point_cloud.h" +#include "pcprep/utils.h" +#include "pcprep/vec3uc.h" +#include "pcprep/wrapper.h" +#include +#include +#include + +pcp_ret_t pcp_point_cloud_init(pcp_point_cloud_t *self) +{ + *self = (pcp_point_cloud_t){0}; + self->alloc = pcp_point_cloud_alloc; + self->load = pcp_point_cloud_load; + self->write = pcp_point_cloud_write; + self->get_min = pcp_point_cloud_get_min; + self->get_max = pcp_point_cloud_get_max; + self->tile = pcp_point_cloud_tile; + self->sample = pcp_point_cloud_sample; + self->remove_dupplicates = pcp_point_cloud_remove_dupplicates; + self->voxelize = pcp_point_cloud_voxelize; + self->get_pixel_per_tile = pcp_point_cloud_get_pixel_per_tile; + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_point_cloud_alloc(pcp_point_cloud_t *pc, size_t size) +{ + pc->size = size; + pc->pos = (float *)malloc(sizeof(float) * 3 * pc->size); + pc->rgb = (uint8_t *)malloc(sizeof(uint8_t) * 3 * pc->size); + if (pc->size < 0) + { + return PCPREP_RET_FAIL; + } + return PCPREP_RET_SUCCESS; +} +pcp_ret_t pcp_point_cloud_free(pcp_point_cloud_t *pc) +{ + if (pc == NULL) + { + return PCPREP_RET_FAIL; + } + if (pc->pos) + { + free(pc->pos); + pc->pos = NULL; + } + if (pc->rgb) + { + free(pc->rgb); + pc->rgb = NULL; + } + return PCPREP_RET_SUCCESS; +} +pcp_ret_t pcp_point_cloud_load(pcp_point_cloud_t *pc, + const char *filename) +{ + pc->alloc(pc, ply_count_vertex(filename)); + if (!ply_pcp_point_cloud_loader(filename, pc->pos, pc->rgb)) + { + return PCPREP_RET_FAIL; + } + return PCPREP_RET_SUCCESS; +} +pcp_ret_t pcp_point_cloud_write(pcp_point_cloud_t *pc, + const char *filename, + int binary) +{ + FILE *file = fopen(filename, "wb"); + if (!file) + { + perror("Error opening file"); + return PCPREP_RET_FAIL; + } + + if (binary) + { + // Binary PLY Header + fprintf(file, "ply\n"); + fprintf(file, "format binary_little_endian 1.0\n"); + fprintf(file, "element vertex %zu\n", pc->size); + fprintf(file, "property float x\n"); + fprintf(file, "property float y\n"); + fprintf(file, "property float z\n"); + fprintf(file, "property uchar red\n"); + fprintf(file, "property uchar green\n"); + fprintf(file, "property uchar blue\n"); + fprintf(file, "end_header\n"); + + for (size_t i = 0; i < pc->size; i++) + { + fwrite(&pc->pos[i * 3], sizeof(float), 3, file); // x, y, z + fwrite(&pc->rgb[i * 3], sizeof(uint8_t), 3, file); // r, g, b + } + } + else + { + // ASCII PLY Header + fprintf(file, "ply\n"); + fprintf(file, "format ascii 1.0\n"); + fprintf(file, "element vertex %zu\n", pc->size); + fprintf(file, "property float x\n"); + fprintf(file, "property float y\n"); + fprintf(file, "property float z\n"); + fprintf(file, "property uchar red\n"); + fprintf(file, "property uchar green\n"); + fprintf(file, "property uchar blue\n"); + fprintf(file, "end_header\n"); + + for (size_t i = 0; i < pc->size; i++) + { + fprintf(file, + "%f %f %f %u %u %u\n", + pc->pos[i * 3], + pc->pos[i * 3 + 1], + pc->pos[i * 3 + 2], + pc->rgb[i * 3], + pc->rgb[i * 3 + 1], + pc->rgb[i * 3 + 2]); + } + } + + fclose(file); + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_point_cloud_get_min(pcp_point_cloud_t *pc, + pcp_vec3f_t *min) +{ + if (!pc->pos) + { + return PCPREP_RET_FAIL; + } + pcp_vec3f_t *pos_lst = (pcp_vec3f_t *)(pc->pos); + *min = pos_lst[0]; + for (int i = 0; i < pc->size; i++) + { + if (pos_lst[i].x < min->x) + min->x = pos_lst[i].x; + if (pos_lst[i].y < min->y) + min->y = pos_lst[i].y; + if (pos_lst[i].z < min->z) + min->z = pos_lst[i].z; + } + return PCPREP_RET_SUCCESS; +} +pcp_ret_t pcp_point_cloud_get_max(pcp_point_cloud_t *pc, + pcp_vec3f_t *max) +{ + if (!pc->pos) + { + return PCPREP_RET_FAIL; + } + pcp_vec3f_t *pos_lst = (pcp_vec3f_t *)(pc->pos); + *max = pos_lst[0]; + for (int i = 0; i < pc->size; i++) + { + if (pos_lst[i].x > max->x) + max->x = pos_lst[i].x; + if (pos_lst[i].y > max->y) + max->y = pos_lst[i].y; + if (pos_lst[i].z > max->z) + max->z = pos_lst[i].z; + } + return PCPREP_RET_SUCCESS; +} + +// TODO: this function is not safe +pcp_ret_t pcp_point_cloud_tile(pcp_point_cloud_t *pc, + int n_x, + int n_y, + int n_z, + pcp_point_cloud_t **tiles) +{ + pcp_vec3f_t min = {0}; + pcp_vec3f_t max = {0}; + pcp_vec3f_t *pos_lst = (pcp_vec3f_t *)pc->pos; + pcp_vec3f_t n = (pcp_vec3f_t){n_x, n_y, n_z}; + int size = n.x * n.y * n.z; + + int *numVerts = (int *)malloc(sizeof(int) * size); + int *tmp = (int *)malloc(sizeof(int) * size); + *tiles = + (pcp_point_cloud_t *)malloc(sizeof(pcp_point_cloud_t) * size); + for (int i = 0; i < size; i++) + { + pcp_point_cloud_init(&(*tiles)[i]); + } + + if (!tiles) + { + free(numVerts); + free(tmp); + return PCPREP_RET_FAIL; + } + + pc->get_min(pc, &min); + pc->get_max(pc, &max); + + for (int t = 0; t < size; t++) + { + numVerts[t] = 0; + tmp[t] = 0; + } + for (int i = 0; i < pc->size; i++) + { + int t = get_tile_id(n, min, max, pos_lst[i]); + numVerts[t]++; + } + + for (int t = 0; t < size; t++) + { + (*tiles)[t].alloc(&(*tiles)[t], numVerts[t]); + } + + for (int i = 0; i < pc->size; i++) + { + int t = get_tile_id(n, min, max, pos_lst[i]); + (*tiles)[t].pos[3 * tmp[t]] = pc->pos[3 * i]; + (*tiles)[t].pos[3 * tmp[t] + 1] = pc->pos[3 * i + 1]; + (*tiles)[t].pos[3 * tmp[t] + 2] = pc->pos[3 * i + 2]; + (*tiles)[t].rgb[3 * tmp[t]] = pc->rgb[3 * i]; + (*tiles)[t].rgb[3 * tmp[t] + 1] = pc->rgb[3 * i + 1]; + (*tiles)[t].rgb[3 * tmp[t] + 2] = pc->rgb[3 * i + 2]; + tmp[t]++; + } + + free(numVerts); + free(tmp); + + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_point_cloud_sample(pcp_point_cloud_t *pc, + float ratio, + unsigned char strategy, + pcp_point_cloud_t *out) +{ + size_t num_points = (size_t)(pc->size * ratio); + + out->alloc(out, num_points); + + switch (strategy) + { + case PCP_SAMPLE_RULE_UNIFORM: + { + int *index_arr = (int *)malloc(sizeof(int) * pc->size); + int *sample = (int *)malloc(num_points * sizeof(int)); + // Seed the random number generator + srand((unsigned int)time(NULL)); + for (int i = 0; i < pc->size; i++) + index_arr[i] = i; + sample_union(index_arr, pc->size, sample, num_points); + for (int i = 0; i < num_points; i++) + { + for (int j = 0; j < 3; j++) + { + out->pos[i * 3 + j] = pc->pos[sample[i] * 3 + j]; + out->rgb[i * 3 + j] = pc->rgb[sample[i] * 3 + j]; + } + } + free(index_arr); + free(sample); + break; + } + default: + break; + } + + return PCPREP_RET_SUCCESS; +} + +static void point_cloud_element_merge(pcp_point_cloud_t pc, + int left, + int mid, + int right) +{ + pcp_vec3f_t *arr_pos = (pcp_vec3f_t *)pc.pos; + pcp_vec3uc_t *arr_col = (pcp_vec3uc_t *)pc.rgb; + + int n1 = mid - left + 1; + int n2 = right - mid; + + pcp_vec3f_t *L_pos = + (pcp_vec3f_t *)malloc(n1 * sizeof(pcp_vec3f_t)); + pcp_vec3f_t *R_pos = + (pcp_vec3f_t *)malloc(n2 * sizeof(pcp_vec3f_t)); + + pcp_vec3uc_t *L_col = + (pcp_vec3uc_t *)malloc(n1 * sizeof(pcp_vec3uc_t)); + pcp_vec3uc_t *R_col = + (pcp_vec3uc_t *)malloc(n2 * sizeof(pcp_vec3uc_t)); + + for (int i = 0; i < n1; i++) + { + *(L_pos + i) = arr_pos[left + i]; + *(L_col + i) = arr_col[left + i]; + } + for (int i = 0; i < n2; i++) + { + *(R_pos + i) = arr_pos[mid + 1 + i]; + *(R_col + i) = arr_col[mid + 1 + i]; + } + int i = 0, j = 0, k = left; + while (i < n1 && j < n2) + { + if (pcp_vec3f_leq(*(L_pos + i), *(R_pos + j))) + { + arr_pos[k] = *(L_pos + i); + arr_col[k++] = *(L_col + i++); + } + else + { + arr_pos[k] = *(R_pos + j); + arr_col[k++] = *(R_col + j++); + } + } + while (i < n1) + { + arr_pos[k] = *(L_pos + i); + arr_col[k++] = *(L_col + i++); + } + while (j < n2) + { + arr_pos[k] = *(R_pos + j); + arr_col[k++] = *(R_col + j++); + } + + free(L_pos); + free(R_pos); + free(L_col); + free(R_col); +} +static void point_cloud_element_merge_sort(pcp_point_cloud_t pc, + int left, + int right) +{ + if (left >= right) + return; + int mid = left + (right - left) / 2; + + point_cloud_element_merge_sort(pc, left, mid); + point_cloud_element_merge_sort(pc, mid + 1, right); + + point_cloud_element_merge(pc, left, mid, right); +} + +pcp_ret_t pcp_point_cloud_remove_dupplicates(pcp_point_cloud_t *pc, + pcp_point_cloud_t *out) +{ + // use mergesort to sort points, then remove consecutives, + // O(Nlog(N)) + point_cloud_element_merge_sort(*pc, 0, pc->size - 1); + + // count unique points to get output size + size_t count_unique = 1; + for (int i = 1; i < pc->size; i++) + { + pcp_vec3f_t pre = ((pcp_vec3f_t *)pc->pos)[i - 1]; + pcp_vec3f_t curr = ((pcp_vec3f_t *)pc->pos)[i]; + if (!pcp_vec3f_eq(pre, curr)) + { + count_unique++; + } + } + out->alloc(out, count_unique); + + // puts the unique points into the output, O(N) + pcp_vec3f_t *uni_pos = (pcp_vec3f_t *)(out->pos); + pcp_vec3uc_t *uni_col = (pcp_vec3uc_t *)(out->rgb); + pcp_vec3f_t *pos = (pcp_vec3f_t *)(pc->pos); + pcp_vec3uc_t *col = (pcp_vec3uc_t *)(pc->rgb); + + int index = 0; + for (int i = 1; i < pc->size; i++) + { + if (!pcp_vec3f_eq(pos[i], pos[i - 1])) + { + uni_pos[index] = pos[i]; + uni_col[index++] = col[i]; // Start the color for the new point + } + } + + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_point_cloud_voxelize(pcp_point_cloud_t *pc, + float voxel_size, + pcp_point_cloud_t *out) +{ + // quantize the points to the voxel grid + // then remove the duplicates, should it tho ? + + out->alloc(out, pc->size); + + memcpy(out->pos, pc->pos, pc->size * sizeof(float) * 3); + memcpy(out->rgb, pc->rgb, pc->size * sizeof(uint8_t) * 3); + + pcp_vec3f_t *pos = (pcp_vec3f_t *)out->pos; + for (int i = 0; i < out->size; i++) + pos[i] = pcp_vec3f_quantize(pos[i], voxel_size); + + // pcp_point_cloud_remove_dupplicates(pc, out); + return PCPREP_RET_SUCCESS; +} + +pcp_ret_t pcp_point_cloud_get_pixel_per_tile(pcp_point_cloud_t *pc, + int nx, + int ny, + int nz, + int width, + int height, + float *mvp, + int *pixel_count) +{ + for (int i = 0; i < nx * ny * nz; i++) + pixel_count[i] = 0; + + pcp_vec3f_t *points = (pcp_vec3f_t *)pc->pos; + pcp_vec3f_t ndc = {0, 0, 0}; + int screen_w = 0; + int screen_h = 0; + int tile_id = 0; + float **minZvalue = NULL; + int16_t **curr_tile = NULL; + pcp_vec3f_t min, max; + pc->get_min(pc, &min); + pc->get_max(pc, &max); + + minZvalue = (float **)malloc(sizeof(float *) * height); + for (int i = 0; i < height; i++) + { + minZvalue[i] = (float *)malloc(sizeof(float) * width); + for (int j = 0; j < width; j++) + minZvalue[i][j] = 2.0f; + // 2 because it is smaller than the max of NDC [-1, 1] + } + + curr_tile = (int16_t **)malloc(sizeof(int16_t *) * height); + for (int i = 0; i < height; i++) + { + curr_tile[i] = (int16_t *)malloc(sizeof(int16_t) * width); + for (int j = 0; j < width; j++) + curr_tile[i][j] = -1; + } + + for (int i = 0; i < pc->size; i++) + { + tile_id = (int)get_tile_id( + (pcp_vec3f_t){nx, ny, nz}, min, max, points[i]); + + pcp_vec3f_t ndc = pcp_vec3f_mvp_mul(points[i], mvp); + // check only if ndc is in side view-frustum + if (ndc.x >= -1 && ndc.x <= 1 && ndc.y >= -1 && ndc.y <= 1 && + ndc.z >= 0 && ndc.z <= 1) + { + // screen_w = (int)((ndc.x + 1.0) * 0.5 * width); + // screen_h = (int)((1.0 - ndc.y) * 0.5 * height); + + screen_w = fminf( + width - 1, fmaxf(0, (int)((ndc.x + 1.0f) * 0.5f * width))); + screen_h = + fminf(height - 1, + fmaxf(0, (int)((1.0f - ndc.y) * 0.5f * height))); + + // If current point is nearer to the camera, then: + // - minZvalue is updated + // curr_tile is also updated + if (ndc.z < minZvalue[screen_h][screen_w]) + { + minZvalue[screen_h][screen_w] = ndc.z; + curr_tile[screen_h][screen_w] = tile_id; + } + } + } + // After we have known each pixel hold the point of which tile, we + // count. + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + if (curr_tile[i][j] >= 0) + { + pixel_count[curr_tile[i][j]]++; + } + } + } + + for (int i = 0; i < height; i++) + free(minZvalue[i]); + free(minZvalue); + for (int i = 0; i < height; i++) + free(curr_tile[i]); + free(curr_tile); + return PCPREP_RET_SUCCESS; +} diff --git a/source/pointcloud.c b/source/pointcloud.c deleted file mode 100644 index 1c3f9b9..0000000 --- a/source/pointcloud.c +++ /dev/null @@ -1,493 +0,0 @@ -#include "pcprep/pointcloud.h" -#include "pcprep/core.h" -#include "pcprep/vec3f.h" -#include "pcprep/vec3uc.h" -#include "pcprep/wrapper.h" -#include -#include -#include - -int pointcloud_init(pointcloud_t *pc, size_t size) -{ - pc->size = size; - pc->pos = (float *)malloc(sizeof(float) * 3 * pc->size); - pc->rgb = (uint8_t *)malloc(sizeof(uint8_t) * 3 * pc->size); - return pc->size; -} -int pointcloud_free(pointcloud_t *pc) -{ - if (pc == NULL) - return 1; - if (pc->pos) - { - free(pc->pos); - pc->pos = NULL; - } - if (pc->rgb) - { - free(pc->rgb); - pc->rgb = NULL; - } - return 1; -} -int pointcloud_load(pointcloud_t *pc, const char *filename) -{ - pointcloud_init(pc, ply_count_vertex(filename)); - return ply_pointcloud_loader(filename, pc->pos, pc->rgb); -} -int pointcloud_write(pointcloud_t pc, - const char *filename, - int binary) -{ - FILE *file = fopen(filename, "wb"); - if (!file) - { - perror("Error opening file"); - return -1; - } - - if (binary) - { - // Binary PLY Header - fprintf(file, "ply\n"); - fprintf(file, "format binary_little_endian 1.0\n"); - fprintf(file, "element vertex %zu\n", pc.size); - fprintf(file, "property float x\n"); - fprintf(file, "property float y\n"); - fprintf(file, "property float z\n"); - fprintf(file, "property uchar red\n"); - fprintf(file, "property uchar green\n"); - fprintf(file, "property uchar blue\n"); - fprintf(file, "end_header\n"); - - for (size_t i = 0; i < pc.size; ++i) - { - fwrite(&pc.pos[i * 3], sizeof(float), 3, file); // x, y, z - fwrite(&pc.rgb[i * 3], sizeof(uint8_t), 3, file); // r, g, b - } - } - else - { - // ASCII PLY Header - fprintf(file, "ply\n"); - fprintf(file, "format ascii 1.0\n"); - fprintf(file, "element vertex %zu\n", pc.size); - fprintf(file, "property float x\n"); - fprintf(file, "property float y\n"); - fprintf(file, "property float z\n"); - fprintf(file, "property uchar red\n"); - fprintf(file, "property uchar green\n"); - fprintf(file, "property uchar blue\n"); - fprintf(file, "end_header\n"); - - for (size_t i = 0; i < pc.size; ++i) - { - fprintf(file, - "%f %f %f %u %u %u\n", - pc.pos[i * 3], - pc.pos[i * 3 + 1], - pc.pos[i * 3 + 2], - pc.rgb[i * 3], - pc.rgb[i * 3 + 1], - pc.rgb[i * 3 + 2]); - } - } - - fclose(file); - return 0; -} - -int pointcloud_min(pointcloud_t pc, vec3f_t *min) -{ - if (!pc.pos) - return -1; - vec3f_t *pos_lst = (vec3f_t *)(pc.pos); - *min = pos_lst[0]; - for (int i = 0; i < pc.size; i++) - { - if (pos_lst[i].x < min->x) - min->x = pos_lst[i].x; - if (pos_lst[i].y < min->y) - min->y = pos_lst[i].y; - if (pos_lst[i].z < min->z) - min->z = pos_lst[i].z; - } - return 0; -} -int pointcloud_max(pointcloud_t pc, vec3f_t *max) -{ - if (!pc.pos) - return -1; - vec3f_t *pos_lst = (vec3f_t *)(pc.pos); - *max = pos_lst[0]; - for (int i = 0; i < pc.size; i++) - { - if (pos_lst[i].x > max->x) - max->x = pos_lst[i].x; - if (pos_lst[i].y > max->y) - max->y = pos_lst[i].y; - if (pos_lst[i].z > max->z) - max->z = pos_lst[i].z; - } - return 0; -} - -int get_tile_id(vec3f_t n, vec3f_t min, vec3f_t max, vec3f_t v) -{ - if (v.x > max.x || v.y > max.y || v.z > max.z || v.x < min.x || - v.y < min.y || v.z < min.z) - return -1; - vec3f_t ans; - // ans = (v - min) / ((max - min) / n); - // or ans = (v - min) * (invs(max - min) / n); - // or ans = (v - min) * (invs(max - min) * invs(n)); - // or ans = (v - min) * invs(max - min) * n); - ans = vec3f_mul(vec3f_mul(vec3f_sub(v, min), - vec3f_inverse(vec3f_sub(max, min))), - n); - ans = (vec3f_t){(int)(ans.x < n.x ? ans.x : n.x - 1), - (int)(ans.y < n.y ? ans.y : n.y - 1), - (int)(ans.z < n.z ? ans.z : n.z - 1)}; - - return ans.z + ans.y * n.z + ans.x * n.y * n.z; -} - -// TODO: this function is not safe -int pointcloud_tile( - pointcloud_t pc, int n_x, int n_y, int n_z, pointcloud_t **tiles) -{ - vec3f_t min, max; - vec3f_t *pos_lst = (vec3f_t *)pc.pos; - vec3f_t n = (vec3f_t){n_x, n_y, n_z}; - int size = n.x * n.y * n.z; - - int *numVerts = (int *)malloc(sizeof(int) * size); - int *tmp = (int *)malloc(sizeof(int) * size); - *tiles = (pointcloud_t *)malloc(sizeof(pointcloud_t) * size); - - if (!tiles) - { - free(numVerts); - free(tmp); - return -1; - } - - pointcloud_min(pc, &min); - pointcloud_max(pc, &max); - - for (int t = 0; t < size; t++) - { - numVerts[t] = 0; - tmp[t] = 0; - } - for (int i = 0; i < pc.size; i++) - { - int t = get_tile_id(n, min, max, pos_lst[i]); - numVerts[t]++; - } - - for (int t = 0; t < size; t++) - { - pointcloud_init(&(*tiles)[t], numVerts[t]); - } - - for (int i = 0; i < pc.size; i++) - { - int t = get_tile_id(n, min, max, pos_lst[i]); - (*tiles)[t].pos[3 * tmp[t]] = pc.pos[3 * i]; - (*tiles)[t].pos[3 * tmp[t] + 1] = pc.pos[3 * i + 1]; - (*tiles)[t].pos[3 * tmp[t] + 2] = pc.pos[3 * i + 2]; - (*tiles)[t].rgb[3 * tmp[t]] = pc.rgb[3 * i]; - (*tiles)[t].rgb[3 * tmp[t] + 1] = pc.rgb[3 * i + 1]; - (*tiles)[t].rgb[3 * tmp[t] + 2] = pc.rgb[3 * i + 2]; - tmp[t]++; - } - - free(numVerts); - free(tmp); - - return size; -} - -int pointcloud_merge(pointcloud_t *pcs, - size_t pc_count, - pointcloud_t *out) -{ - size_t total_size = 0; - for (int i = 0; i < pc_count; i++) - total_size += pcs[i].size; - if (pointcloud_init(out, total_size) < 0) - { - return -1; // Memory allocation failed - } - - int curr = 0; - for (int i = 0; i < pc_count; i++) - { - memcpy((char *)(out->pos + curr * 3), - (char *)pcs[i].pos, - pcs[i].size * 3 * sizeof(float)); - memcpy((char *)(out->rgb + curr * 3), - (char *)pcs[i].rgb, - pcs[i].size * 3 * sizeof(uint8_t)); - curr += pcs[i].size; - } - return 1; -} - -int pointcloud_sample(pointcloud_t pc, - float ratio, - unsigned char strategy, - pointcloud_t *out) -{ - size_t num_points = (size_t)(pc.size * ratio); - - pointcloud_init(out, num_points); - - switch (strategy) - { - case PCP_SAMPLE_RULE_UNIFORM: - { - int *index_arr = (int *)malloc(sizeof(int) * pc.size); - int *sample = (int *)malloc(num_points * sizeof(int)); - // Seed the random number generator - srand((unsigned int)time(NULL)); - for (int i = 0; i < pc.size; i++) - index_arr[i] = i; - sample_union(index_arr, pc.size, sample, num_points); - for (int i = 0; i < num_points; i++) - { - for (int j = 0; j < 3; j++) - { - out->pos[i * 3 + j] = pc.pos[sample[i] * 3 + j]; - out->rgb[i * 3 + j] = pc.rgb[sample[i] * 3 + j]; - } - } - free(index_arr); - free(sample); - break; - } - default: - break; - } - - return 1; -} - -static void pointcloud_element_merge(pointcloud_t pc, - int left, - int mid, - int right) -{ - vec3f_t *arr_pos = (vec3f_t *)pc.pos; - vec3uc_t *arr_col = (vec3uc_t *)pc.rgb; - - int n1 = mid - left + 1; - int n2 = right - mid; - - vec3f_t *L_pos = (vec3f_t *)malloc(n1 * sizeof(vec3f_t)); - vec3f_t *R_pos = (vec3f_t *)malloc(n2 * sizeof(vec3f_t)); - - vec3uc_t *L_col = (vec3uc_t *)malloc(n1 * sizeof(vec3uc_t)); - vec3uc_t *R_col = (vec3uc_t *)malloc(n2 * sizeof(vec3uc_t)); - - for (int i = 0; i < n1; i++) - { - *(L_pos + i) = arr_pos[left + i]; - *(L_col + i) = arr_col[left + i]; - } - for (int i = 0; i < n2; i++) - { - *(R_pos + i) = arr_pos[mid + 1 + i]; - *(R_col + i) = arr_col[mid + 1 + i]; - } - int i = 0, j = 0, k = left; - while (i < n1 && j < n2) - { - if (vec3f_leq(*(L_pos + i), *(R_pos + j))) - { - arr_pos[k] = *(L_pos + i); - arr_col[k++] = *(L_col + i++); - } - else - { - arr_pos[k] = *(R_pos + j); - arr_col[k++] = *(R_col + j++); - } - } - while (i < n1) - { - arr_pos[k] = *(L_pos + i); - arr_col[k++] = *(L_col + i++); - } - while (j < n2) - { - arr_pos[k] = *(R_pos + j); - arr_col[k++] = *(R_col + j++); - } - - free(L_pos); - free(R_pos); - free(L_col); - free(R_col); -} -static void -pointcloud_element_merge_sort(pointcloud_t pc, int left, int right) -{ - if (left >= right) - return; - int mid = left + (right - left) / 2; - - pointcloud_element_merge_sort(pc, left, mid); - pointcloud_element_merge_sort(pc, mid + 1, right); - - pointcloud_element_merge(pc, left, mid, right); -} - -int pointcloud_remove_dupplicates(pointcloud_t pc, pointcloud_t *out) -{ - // use mergesort to sort points, then remove consecutives, - // O(Nlog(N)) - pointcloud_element_merge_sort(pc, 0, pc.size - 1); - - // count unique points to get output size - size_t count_unique = 1; - for (int i = 1; i < pc.size; i++) - { - vec3f_t pre = ((vec3f_t *)pc.pos)[i - 1]; - vec3f_t curr = ((vec3f_t *)pc.pos)[i]; - if (!vec3f_eq(pre, curr)) - { - count_unique++; - } - } - pointcloud_init(out, count_unique); - - // puts the unique points into the output, O(N) - vec3f_t *uni_pos = (vec3f_t *)(out->pos); - vec3uc_t *uni_col = (vec3uc_t *)(out->rgb); - vec3f_t *pos = (vec3f_t *)(pc.pos); - vec3uc_t *col = (vec3uc_t *)(pc.rgb); - - int index = 0; - for (int i = 1; i < pc.size; i++) - { - if (!vec3f_eq(pos[i], pos[i - 1])) - { - uni_pos[index] = pos[i]; - uni_col[index++] = col[i]; // Start the color for the new point - } - } - - return out->size; -} - -int pointcloud_voxel(pointcloud_t pc, - float voxel_size, - pointcloud_t *out) -{ - // quantize the points to the voxel grid - // then remove the duplicates, should it tho ? - - pointcloud_init(out, pc.size); - - memcpy(out->pos, pc.pos, pc.size * sizeof(float) * 3); - memcpy(out->rgb, pc.rgb, pc.size * sizeof(uint8_t) * 3); - - vec3f_t *pos = (vec3f_t *)out->pos; - for (int i = 0; i < out->size; i++) - pos[i] = vec3f_quantize(pos[i], voxel_size); - - // pointcloud_remove_dupplicates(pc, out); -} - -int pointcloud_count_pixel_per_tile(pointcloud_t pc, - int nx, - int ny, - int nz, - int width, - int height, - float *mvp, - int *pixel_count) -{ - for (int i = 0; i < nx * ny * nz; i++) - pixel_count[i] = 0; - - vec3f_t *points = (vec3f_t *)pc.pos; - vec3f_t ndc = {0, 0, 0}; - int screen_w = 0; - int screen_h = 0; - int tile_id = 0; - float **minZvalue = NULL; - int16_t **curr_tile = NULL; - vec3f_t min, max; - pointcloud_min(pc, &min); - pointcloud_max(pc, &max); - - minZvalue = (float **)malloc(sizeof(float *) * height); - for (int i = 0; i < height; i++) - { - minZvalue[i] = (float *)malloc(sizeof(float) * width); - for (int j = 0; j < width; j++) - minZvalue[i][j] = 2.0f; - // 2 because it is smaller than the max of NDC [-1, 1] - } - - curr_tile = (int16_t **)malloc(sizeof(int16_t *) * height); - for (int i = 0; i < height; i++) - { - curr_tile[i] = (int16_t *)malloc(sizeof(int16_t) * width); - for (int j = 0; j < width; j++) - curr_tile[i][j] = -1; - } - - for (int i = 0; i < pc.size; i++) - { - tile_id = - (int)get_tile_id((vec3f_t){nx, ny, nz}, min, max, points[i]); - - vec3f_t ndc = vec3f_mvp_mul(points[i], mvp); - // check only if ndc is in side view-frustum - if (ndc.x >= -1 && ndc.x <= 1 && ndc.y >= -1 && ndc.y <= 1 && - ndc.z >= 0 && ndc.z <= 1) - { - // screen_w = (int)((ndc.x + 1.0) * 0.5 * width); - // screen_h = (int)((1.0 - ndc.y) * 0.5 * height); - - screen_w = fminf( - width - 1, fmaxf(0, (int)((ndc.x + 1.0f) * 0.5f * width))); - screen_h = - fminf(height - 1, - fmaxf(0, (int)((1.0f - ndc.y) * 0.5f * height))); - - // If current point is nearer to the camera, then: - // - minZvalue is updated - // curr_tile is also updated - if (ndc.z < minZvalue[screen_h][screen_w]) - { - minZvalue[screen_h][screen_w] = ndc.z; - curr_tile[screen_h][screen_w] = tile_id; - } - } - } - // After we have known each pixel hold the point of which tile, we - // count. - for (int i = 0; i < height; i++) - { - for (int j = 0; j < width; j++) - { - if (curr_tile[i][j] >= 0) - { - pixel_count[curr_tile[i][j]]++; - } - } - } - - for (int i = 0; i < height; i++) - free(minZvalue[i]); - free(minZvalue); - for (int i = 0; i < height; i++) - free(curr_tile[i]); - free(curr_tile); - return 1; -} diff --git a/source/core.c b/source/utils.c similarity index 86% rename from source/core.c rename to source/utils.c index 423985e..6ea492e 100644 --- a/source/core.c +++ b/source/utils.c @@ -1,7 +1,9 @@ #define _POSIX_C_SOURCE 199309L #include #include -#include +#include +#include +#include #include #include #include @@ -387,3 +389,53 @@ int save_viewport(unsigned char **row_pointers, png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); } + +int get_tile_id(pcp_vec3f_t n, + pcp_vec3f_t min, + pcp_vec3f_t max, + pcp_vec3f_t v) +{ + if (v.x > max.x || v.y > max.y || v.z > max.z || v.x < min.x || + v.y < min.y || v.z < min.z) + return -1; + pcp_vec3f_t ans; + // ans = (v - min) / ((max - min) / n); + // or ans = (v - min) * (invs(max - min) / n); + // or ans = (v - min) * (invs(max - min) * invs(n)); + // or ans = (v - min) * invs(max - min) * n); + ans = pcp_vec3f_mul( + pcp_vec3f_mul(pcp_vec3f_sub(v, min), + pcp_vec3f_inverse(pcp_vec3f_sub(max, min))), + n); + ans = (pcp_vec3f_t){(int)(ans.x < n.x ? ans.x : n.x - 1), + (int)(ans.y < n.y ? ans.y : n.y - 1), + (int)(ans.z < n.z ? ans.z : n.z - 1)}; + + return ans.z + ans.y * n.z + ans.x * n.y * n.z; +} + +int point_cloud_merge(pcp_point_cloud_t *pcs, + size_t pc_count, + pcp_point_cloud_t *out) +{ + size_t total_size = 0; + for (int i = 0; i < pc_count; i++) + total_size += pcs[i].size; + if (out->alloc(out, total_size) == PCPREP_RET_FAIL) + { + return -1; // Memory allocation failed + } + + int curr = 0; + for (int i = 0; i < pc_count; i++) + { + memcpy((char *)(out->pos + curr * 3), + (char *)pcs[i].pos, + pcs[i].size * 3 * sizeof(float)); + memcpy((char *)(out->rgb + curr * 3), + (char *)pcs[i].rgb, + pcs[i].size * 3 * sizeof(uint8_t)); + curr += pcs[i].size; + } + return 1; +} diff --git a/source/wrapper.cpp b/source/wrapper.cpp index b217dc8..0212575 100644 --- a/source/wrapper.cpp +++ b/source/wrapper.cpp @@ -119,7 +119,7 @@ extern "C" return reader.get_element(elemIndex)->count; } // Wrapper implementation - int ply_pointcloud_loader(const char *filename, + int ply_pcp_point_cloud_loader(const char *filename, float *pos, unsigned char *rgb) { diff --git a/test/source/pc_io.c b/test/source/pc_io.c index e693bcf..ec7fd11 100644 --- a/test/source/pc_io.c +++ b/test/source/pc_io.c @@ -1,16 +1,15 @@ -#include +#include #include int main(int argc, char *argv[]) { - pointcloud_t pc; - pc.rgb = NULL; - pc.pos = NULL; - pc.size = 0; + pcp_point_cloud_t pc = {0}; - int prep = pointcloud_load(&pc, argv[1]); + pcp_point_cloud_init(&pc); + + int prep = pc.load(&pc, argv[1]); printf("%lu\n", pc.size); printf("%f\n", pc.pos[123]); - pointcloud_write(pc, "out_msh.ply", 1); - pointcloud_free(&pc); + pc.write(&pc, "out_msh.ply", 1); + pcp_point_cloud_free(&pc); } diff --git a/test/source/subsampling.c b/test/source/subsampling.c index d753fb7..2068601 100644 --- a/test/source/subsampling.c +++ b/test/source/subsampling.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -48,18 +48,21 @@ int main(int argc, char *argv[]) return 1; } - pointcloud_t pc = {0}; - pointcloud_t sub = {0}; - float NvertPercent = 0; - int subVerts = 0; - int *index_arr = NULL; - int *sample = NULL; + pcp_point_cloud_t pc = {0}; + pcp_point_cloud_t sub = {0}; + float NvertPercent = 0; + int subVerts = 0; + int *index_arr = NULL; + int *sample = NULL; - pointcloud_load(&pc, argv[1]); + pcp_point_cloud_init(&pc); + pcp_point_cloud_init(&sub); + + pc.load(&pc, argv[1]); NvertPercent = atof(argv[2]); subVerts = (int)(pc.size * NvertPercent); - pointcloud_init(&sub, subVerts); + sub.alloc(&sub, subVerts); index_arr = (int *)malloc(sizeof(int) * pc.size); sample = (int *)malloc(subVerts * sizeof(int)); srand((unsigned int)time(NULL)); // Seed the random number generator @@ -77,10 +80,10 @@ int main(int argc, char *argv[]) sub.rgb[i * 3 + j] = pc.rgb[sample[i] * 3 + j]; } } - pointcloud_write(sub, argv[3], 1); + sub.write(&sub, argv[3], 1); - pointcloud_free(&pc); - pointcloud_free(&sub); + pcp_point_cloud_free(&pc); + pcp_point_cloud_free(&sub); free(index_arr); free(sample); } diff --git a/test/source/tiling.c b/test/source/tiling.c index c428e21..7a6f46e 100644 --- a/test/source/tiling.c +++ b/test/source/tiling.c @@ -1,4 +1,4 @@ -#include +#include #include #include @@ -16,20 +16,23 @@ int main(int argc, char *argv[]) return 1; } // Parse command-line arguments - const char *input_file_path = argv[1]; - int n_x = atoi(argv[2]); - int n_y = atoi(argv[3]); - int n_z = atoi(argv[4]); - int isBinary = atoi(argv[5]); - char *out_folder = argv[6]; - char out_file_name[1024]; - pointcloud_t pc = {0}; - pointcloud_t *tiles = NULL; - struct stat st = {0}; - int tile_count = 0; + const char *input_file_path = argv[1]; + int n_x = atoi(argv[2]); + int n_y = atoi(argv[3]); + int n_z = atoi(argv[4]); + int isBinary = atoi(argv[5]); + char *out_folder = argv[6]; + char out_file_name[1024]; + pcp_point_cloud_t pc = {0}; + pcp_point_cloud_t *tiles = NULL; + struct stat st = {0}; + int tile_count = 0; - pointcloud_load(&pc, input_file_path); - tile_count = pointcloud_tile(pc, n_x, n_y, n_z, &tiles); + pcp_point_cloud_init(&pc); + + pc.load(&pc, input_file_path); + tile_count = n_x * n_y * n_z; + pc.tile(&pc, n_x, n_y, n_z, &tiles); if (stat(out_folder, &st) == -1) { @@ -47,11 +50,11 @@ int main(int argc, char *argv[]) "%s/tile%.04d.ply", out_folder, t); - pointcloud_write(tiles[t], out_file_name, isBinary); + tiles[t].write(&tiles[t], out_file_name, isBinary); } - pointcloud_free(&pc); + pcp_point_cloud_free(&pc); for (int i = 0; i < tile_count; i++) - pointcloud_free(&tiles[i]); + pcp_point_cloud_free(&tiles[i]); free(tiles); }