stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit 186417f36f9948f54242aa2e71eb2e7f697a3a10
parent 89a53b0130ea7bcdaf0925c9f8cdf7e1e4fedcc5
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu,  9 Apr 2020 15:48:15 +0200

Add auto look at functionality for -R option to comply with documentation

Diffstat:
Msrc/stardis-app.c | 12++++++------
Msrc/stardis-app.h | 4+++-
Msrc/stardis-compute.c | 89++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/stardis-parsing.c | 2++
4 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -667,23 +667,23 @@ ensure_allocated(struct str* str, const size_t len, const char keep_old) size_t new_size = 0; ASSERT(str); - if (len * sizeof(char) <= str->allocated) + if(len * sizeof(char) <= str->allocated) return RES_OK; mod = len % alloc_granularity; new_len = !mod ? len : len - mod + alloc_granularity; new_size = new_len * sizeof(char); buf = MEM_ALLOC(str->allocator, new_size); - if (!buf) + if(!buf) return RES_MEM_ERR; - if (keep_old) { + if(keep_old) { strncpy(buf, str->cstr, new_len - 1); buf[new_len - 1] = '\0'; } str->allocated = new_len * sizeof(char); - if (str->cstr != str->buffer) + if(str->cstr != str->buffer) MEM_RM(str->allocator, str->cstr); str->cstr = buf; @@ -706,11 +706,11 @@ str_printf initial_len = str_len(str); ASSERT(str->allocated >= initial_len); left = str->allocated - initial_len; - if (left) { + if(left) { VA_COPY(args_cp, args); needed = (size_t)vsnprintf(str->cstr + initial_len, left, fmt, args_cp); } - if (needed >= left) { + if(needed >= left) { ERR(ensure_allocated(str, initial_len + needed + 1, 1)); ASSERT(str->allocated >= initial_len); left = str->allocated - initial_len; diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -665,9 +665,10 @@ struct camera { double tgt[3]; double up[3]; double fov; + double time; unsigned spp; unsigned img_width, img_height; - double time; + int auto_look_at; }; static INLINE void @@ -680,6 +681,7 @@ init_camera(struct camera* cam) { cam->img_width = STARDIS_DEFAULT_RENDERING_IMG_WIDTH; cam->img_height = STARDIS_DEFAULT_RENDERING_IMG_HEIGHT; cam->time = STARDIS_DEFAULT_RENDERING_TIME; + cam->auto_look_at = 1; } static INLINE void diff --git a/src/stardis-compute.c b/src/stardis-compute.c @@ -251,10 +251,88 @@ error: } static res_T -compute_camera(const struct stardis* stardis) +auto_look_at + (struct sdis_scene* scn, + const double fov_x, /* Horizontal field of view in radian */ + const double proj_ratio, /* Width / height */ + const double up[3], /* Up vector */ + double position[3], + double target[3]) +{ + double lower[3], upper[3]; + double up_abs[3]; + double axis_min[3]; + double axis_x[3]; + double axis_z[3]; + double tmp[3]; + double radius; + double depth; + res_T res; + ASSERT(scn && fov_x && proj_ratio && up); + + ERR(sdis_scene_get_aabb(scn, lower, upper)); + + if(lower[0] > upper[0] || lower[1] > upper[1] || lower[2] > upper[2]) { + /* Empty scene */ + d3(position, STARDIS_DEFAULT_RENDERING_POS); + d3(target, STARDIS_DEFAULT_RENDERING_TGT); + goto exit; + } + + /* The target is the scene centroid */ + d3_muld(target, d3_add(target, lower, upper), 0.5); + + /* Define which up dimension is minimal and use its unit vector to compute a + * vector orthogonal to `up'. This ensures that the unit vector and `up' are + * not collinear so that their cross product is not a zero vector. */ + up_abs[0] = fabs(up[0]); + up_abs[1] = fabs(up[1]); + up_abs[2] = fabs(up[2]); + if(up_abs[0] < up_abs[1]) { + if(up_abs[0] < up_abs[2]) d3(axis_min, 1, 0, 0); + else d3(axis_min, 0, 0, 1); + } else { + if(up_abs[1] < up_abs[2]) d3(axis_min, 0, 1, 0); + else d3(axis_min, 0, 0, 1); + } + d3_normalize(axis_x, d3_cross(axis_x, up, axis_min)); + d3_normalize(axis_z, d3_cross(axis_z, up, axis_x)); + + /* Find whether the XYZ or the ZYX basis maximise the model's visibility */ + if(fabs(d3_dot(axis_x, upper)) < fabs(d3_dot(axis_z, upper))) { + SWAP(double, axis_x[0], axis_z[0]); + SWAP(double, axis_x[1], axis_z[1]); + SWAP(double, axis_x[2], axis_z[2]); + } + + /* Ensure that the whole model is visible */ + radius = d3_len(d3_sub(tmp, upper, lower)) * 0.5; + if(proj_ratio < 1) { + depth = radius / sin(fov_x / 2.0); + } else { + depth = radius / sin(fov_x / (2.0 * proj_ratio)); + } + + /* Define the camera position */ + d3_sub(position, target, d3_muld(tmp, axis_z, depth)); + + /* Empirically move the position to find a better point of view */ + d3_add(position, position, d3_muld(tmp, up, radius)); /*Empirical offset*/ + d3_add(position, position, d3_muld(tmp, axis_x, radius)); /*Empirical offset*/ + d3_normalize(tmp, d3_sub(tmp, target, position)); + d3_sub(position, target, d3_muld(tmp, tmp, depth)); + +exit: + return res; +error: + goto exit; +} + +static res_T +compute_camera(struct stardis* stardis) { res_T res = RES_OK; - double time[2]; + double proj_ratio, time[2]; size_t width, height; struct sdis_estimator_buffer* buf = NULL; struct sdis_camera* cam = NULL; @@ -264,10 +342,15 @@ compute_camera(const struct stardis* stardis) width = (size_t)stardis->camera.img_width; height = (size_t)stardis->camera.img_height; + proj_ratio = (double)width / (double)height; /* Setup the camera */ ERR(sdis_camera_create(stardis->dev, &cam)); - ERR(sdis_camera_set_proj_ratio(cam, (double)width / (double)height)); + ERR(sdis_camera_set_proj_ratio(cam, proj_ratio)); ERR(sdis_camera_set_fov(cam, MDEG2RAD(stardis->camera.fov))); + if(stardis->camera.auto_look_at) { + ERR(auto_look_at(stardis->sdis_scn, MDEG2RAD(stardis->camera.fov), proj_ratio, + stardis->camera.up, stardis->camera.pos, stardis->camera.tgt)); + } ERR(sdis_camera_look_at(cam, stardis->camera.pos, stardis->camera.tgt, diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -873,9 +873,11 @@ parse_camera } else if(strcmp(opt[0], "TGT") == 0) { ERR(cstr_to_list_double(opt[1], ',', cam->tgt, &len, 3)); + cam->auto_look_at = 0; } else if(strcmp(opt[0], "POS") == 0) { ERR(cstr_to_list_double(opt[1], ',', cam->pos, &len, 3)); + cam->auto_look_at = 0; } else if(strcmp(opt[0], "IMG") == 0) { unsigned img_sz[2];