star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

commit 8e85a6d7b3f8687179c5a63e5c3ffc702db818fe
parent 5a752e8ee7189657c47d033a47bf57daf321d1b9
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 26 Oct 2016 11:04:27 +0200

Improve the trace ray test on instances

Draw an image of instantiated Cornell Boxes

Diffstat:
Asrc/test_s3d_camera.h | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_s3d_cbox.h | 2+-
Msrc/test_s3d_trace_ray.c | 49+++++++------------------------------------------
Msrc/test_s3d_trace_ray_instance.c | 173+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 254 insertions(+), 51 deletions(-)

diff --git a/src/test_s3d_camera.h b/src/test_s3d_camera.h @@ -0,0 +1,81 @@ +/* Copyright (C) |Meso|Star> 2015-2016 (contact@meso-star.com) + * + * This software is a computer program whose purpose is to describe a + * virtual 3D environment that can be ray-traced and sampled both robustly + * and efficiently. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. */ + +#ifndef TEST_S3D_CAMERA_H +#define TEST_S3D_CAMERA_H + +#include <rsys/float3.h> + +struct camera { + float pos[3]; + float x[3], y[3], z[3]; /* Basis */ +}; + +static INLINE void +camera_init + (struct camera* cam, + const float pos[3], + const float tgt[3], + const float up[3], + const float fov_x, + const float proj_ratio) +{ + float f = 0.f; + ASSERT(cam); + + f3_set(cam->pos, pos); + f = f3_normalize(cam->z, f3_sub(cam->z, tgt, pos)); NCHECK(f, 0); + f = f3_normalize(cam->x, f3_cross(cam->x, cam->z, up)); NCHECK(f, 0); + f = f3_normalize(cam->y, f3_cross(cam->y, cam->z, cam->x)); NCHECK(f, 0); + f3_divf(cam->z, cam->z, (float)tan(fov_x*0.5f)); + f3_divf(cam->y, cam->y, proj_ratio); +} + +static INLINE void +camera_ray + (const struct camera* cam, + const float pixel[2], + float org[3], + float dir[3]) +{ + float x[3], y[3], f; + ASSERT(cam && pixel && org && dir); + + f3_mulf(x, cam->x, pixel[0]*2.f - 1.f); + f3_mulf(y, cam->y, pixel[1]*2.f - 1.f); + f3_add(dir, f3_add(dir, x, y), cam->z); + f = f3_normalize(dir, dir); NCHECK(f, 0); + f3_set(org, cam->pos); +} + +#endif /* TEST_S3D_CAMERA_H */ + diff --git a/src/test_s3d_cbox.h b/src/test_s3d_cbox.h @@ -36,7 +36,7 @@ #include <rsys/rsys.h> #include <stdint.h> -struct cbox_desc{ +struct cbox_desc { const float* vertices; const unsigned* indices; }; diff --git a/src/test_s3d_trace_ray.c b/src/test_s3d_trace_ray.c @@ -31,6 +31,7 @@ * knowledge of the CeCILL license and that you accept its terms. */ #include "s3d.h" +#include "test_s3d_camera.h" #include "test_s3d_cbox.h" #include "test_s3d_utils.h" @@ -42,47 +43,6 @@ #define IMG_WIDTH 640 #define IMG_HEIGHT 480 -struct camera { - float pos[3]; - float x[3], y[3], z[3]; /* Basis */ -}; - -static void -camera_init(struct camera* cam) -{ - const float pos[3] = { 178.f, -1000.f, 273.f }; - const float tgt[3] = { 178.f, 0.f, 273.f }; - const float up[3] = { 0.f, 0.f, 1.f }; - const float proj_ratio = (float)IMG_WIDTH/(float)IMG_HEIGHT; - const float fov_x = (float)PI * 0.25f; - float f = 0.f; - ASSERT(cam); - - f3_set(cam->pos, pos); - f = f3_normalize(cam->z, f3_sub(cam->z, tgt, pos)); NCHECK(f, 0); - f = f3_normalize(cam->x, f3_cross(cam->x, cam->z, up)); NCHECK(f, 0); - f = f3_normalize(cam->y, f3_cross(cam->y, cam->z, cam->x)); NCHECK(f, 0); - f3_divf(cam->z, cam->z, (float)tan(fov_x*0.5f)); - f3_divf(cam->y, cam->y, proj_ratio); -} - -static void -camera_ray - (const struct camera* cam, - const float pixel[2], - float org[3], - float dir[3]) -{ - float x[3], y[3], f; - ASSERT(cam && pixel && org && dir); - - f3_mulf(x, cam->x, pixel[0]*2.f - 1.f); - f3_mulf(y, cam->y, pixel[1]*2.f - 1.f); - f3_add(dir, f3_add(dir, x, y), cam->z); - f = f3_normalize(dir, dir); NCHECK(f, 0); - f3_set(org, cam->pos); -} - static int filter_func (const struct s3d_hit* hit, @@ -125,6 +85,7 @@ main(int argc, char** argv) float transform[12]; float vec[3]; float lower[3], upper[3]; + float pos[3], tgt[3], up[3]; float org[3] = { 0.f, 0.f, 0.f }; float dir[3] = { 0.f, 1.f, 0.f }; float range[2] = { 0.f, FLT_MAX }; @@ -314,7 +275,11 @@ main(int argc, char** argv) CHECK(f3_eq(transform + 9, f3(vec, -100.f, 0.f, -2.f)), 1); } - camera_init(&cam); + f3(pos, 178.f, -1000.f, 273.f); + f3(tgt, 178.f, 0.f, 273.f); + f3(up, 0.f, 0.f, 1.f); + camera_init(&cam, pos, tgt, up, (float)PI*0.25, + (float)IMG_WIDTH/(float)IMG_HEIGHT); FOR_EACH(iy, 0, IMG_HEIGHT) { float pixel[2]; diff --git a/src/test_s3d_trace_ray_instance.c b/src/test_s3d_trace_ray_instance.c @@ -31,11 +31,14 @@ * knowledge of the CeCILL license and that you accept its terms. */ #include "s3d.h" +#include "test_s3d_camera.h" +#include "test_s3d_cbox.h" #include "test_s3d_utils.h" #include <rsys/float2.h> #include <rsys/float3.h> #include <rsys/float33.h> +#include <rsys/image.h> static const float quad_verts[] = { -1.f, -1.f, 0.f, @@ -95,13 +98,11 @@ quad_get_pos(const unsigned ivert, float pos[3], void* data) pos[2] = quad_verts[i+2]; } -int -main(int argc, char** argv) +static void +test_quad(struct s3d_device* dev) { - struct mem_allocator allocator; struct ray ray; struct s3d_attrib attr; - struct s3d_device* dev; struct s3d_hit hit[2]; struct s3d_scene* scn; struct s3d_scene_view* view[2]; @@ -113,10 +114,6 @@ main(int argc, char** argv) float transform[12]; float dir[3]; float range[2]; - (void)argc, (void)argv; - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - CHECK(s3d_device_create(NULL, &allocator, 1, &dev), RES_OK); f33_rotation_pitch(transform, (float)PI); f3_splat(transform+9, 0); @@ -181,6 +178,166 @@ main(int argc, char** argv) CHECK(s3d_shape_ref_put(quad_inst), RES_OK); CHECK(s3d_shape_ref_put(quad), RES_OK); CHECK(s3d_scene_ref_put(scn), RES_OK); +} + +static void +test_cbox(struct s3d_device* dev, const char* filename) +{ + struct camera cam; + struct cbox_desc cbox_desc; + struct s3d_scene* scn; + struct s3d_scene* cbox; + struct s3d_shape* shape; + struct s3d_vertex_data vdata; + struct s3d_scene_view* view; + float lower[3], upper[3], extend[3]; + float size[2]; + float pos[3], tgt[3], up[3]; + float org[3], dir[3], range[2]; + float proj_ratio; + unsigned char* img = NULL; + unsigned walls_id; + const int img_sz[2] = { 640, 480 }; + const int N = 8; + int x, y; + + CHECK(s3d_scene_create(dev, &cbox), RES_OK); + CHECK(s3d_scene_create(dev, &scn), RES_OK); + + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = cbox_get_position; + + /* Walls */ + cbox_desc.vertices = cbox_walls; + cbox_desc.indices = cbox_walls_ids; + CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); + CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_walls_ntris, cbox_get_ids, + cbox_walls_nverts, &vdata, 1, &cbox_desc), RES_OK); + CHECK(s3d_scene_attach_shape(cbox, shape), RES_OK); + CHECK(s3d_shape_get_id(shape, &walls_id), RES_OK); + CHECK(s3d_shape_ref_put(shape), RES_OK); + + /* Short block */ + cbox_desc.vertices = cbox_short_block; + cbox_desc.indices = cbox_block_ids; + CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); + CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, + cbox_block_nverts, &vdata, 1, &cbox_desc), RES_OK); + CHECK(s3d_scene_attach_shape(cbox, shape), RES_OK); + CHECK(s3d_shape_ref_put(shape), RES_OK); + + /* Tall block */ + cbox_desc.vertices = cbox_tall_block; + cbox_desc.indices = cbox_block_ids; + CHECK(s3d_shape_create_mesh(dev, &shape), RES_OK); + CHECK(s3d_mesh_setup_indexed_vertices(shape, cbox_block_ntris, cbox_get_ids, + cbox_block_nverts, &vdata, 1, &cbox_desc), RES_OK); + CHECK(s3d_scene_attach_shape(cbox, shape), RES_OK); + CHECK(s3d_shape_ref_put(shape), RES_OK); + + /* Compute the cbox extends */ + CHECK(s3d_scene_view_create(cbox, S3D_GET_PRIMITIVE, &view), RES_OK); + CHECK(s3d_scene_view_get_aabb(view, lower, upper), RES_OK); + CHECK(s3d_scene_view_ref_put(view), RES_OK); + f3_sub(extend, upper, lower); + + /* Create instances */ + size[0] = extend[0]*(float)N + (extend[0]*0.05f) * (float)(N-1); + size[1] = extend[2]*(float)N + (extend[2]*0.05f) * (float)(N-1); + pos[0] = -size[0] * 0.5f; + pos[1] = 0; + FOR_EACH(x, 0, N) { + pos[2] = -size[1] * 0.5f; + FOR_EACH(y, 0, N) { + CHECK(s3d_scene_instantiate(cbox, &shape), RES_OK); + CHECK(s3d_instance_set_position(shape, pos), RES_OK); + CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); + CHECK(s3d_shape_ref_put(shape), RES_OK); + pos[2] += extend[2] * 1.05f; + } + pos[0] += extend[0] * 1.05f; + } + + /* Setup point of view */ + f3(pos, 0.f, -3000.f, 0.f); + f3(tgt, 0.f, 0.f, 0.f); + f3(up, 0.f, 0.f, 1.f); + proj_ratio = (float)img_sz[0] / (float)img_sz[1]; + camera_init(&cam, pos, tgt, up, (float)PI*0.5, proj_ratio); + + /* Create the output image */ + if(filename) { + img = mem_alloc((size_t)(3*img_sz[0]*img_sz[1])); + NCHECK(img, NULL); + } + + /* Trace rays */ + CHECK(s3d_scene_view_create(scn, S3D_TRACE, &view), RES_OK); + range[0] = 0.f; + range[1] = FLT_MAX; + FOR_EACH(y, 0, img_sz[1]) { + float pixel[2]; + pixel[1] = (float)y / (float)img_sz[1]; + FOR_EACH(x, 0, img_sz[0]) { + const int ipix = (y*img_sz[0] + x)*3/*RGB*/; + struct s3d_hit hit; + + pixel[0] = (float)x/(float)img_sz[0]; + camera_ray(&cam, pixel, org, dir); + CHECK(s3d_scene_view_trace_ray(view, org, dir, range, NULL, &hit), RES_OK); + if(!img) continue; + + if(S3D_HIT_NONE(&hit)) { + img[ipix+0] = 0; + img[ipix+1] = 0; + img[ipix+2] = 0; + } else { + float normal[3], col[3], dot; + float f = (float)hit.prim.inst_id / (float)(N*N); + f3(col, f, MMAX(0.f, 1.f-f), MMAX(0.f, 1.f-f)); + + if(hit.prim.geom_id == walls_id) { + if(hit.prim.prim_id == 4 || hit.prim.prim_id == 5) { + f3(col, col[0], 0.f, 0.f); + } else if(hit.prim.prim_id == 6 || hit.prim.prim_id == 7) { + f3(col, 0.f, col[1], 0.f); + } + } + + f3_normalize(normal, hit.normal); + dot = absf(f3_dot(normal, dir)); + img[ipix+0] = (unsigned char)(dot * col[0] * 255.f); + img[ipix+1] = (unsigned char)(dot * col[1] * 255.f); + img[ipix+2] = (unsigned char)(dot * col[2] * 255.f); + } + } + } + CHECK(s3d_scene_view_ref_put(view), RES_OK); + + if(img) { + CHECK(image_ppm_write(filename, img_sz[0], img_sz[1], 3, img), RES_OK); + mem_rm(img); + } + + /* Release data */ + CHECK(s3d_scene_ref_put(cbox), RES_OK); + CHECK(s3d_scene_ref_put(scn), RES_OK); +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct s3d_device* dev; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + CHECK(s3d_device_create(NULL, &allocator, 1, &dev), RES_OK); + + test_quad(dev); + test_cbox(dev, argc > 1 ? argv[1] : NULL); + CHECK(s3d_device_ref_put(dev), RES_OK); check_memory_allocator(&allocator);