| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- #include "scene_render.h"
- #include "render/render_mesh.h"
- #include <glm/gtc/matrix_access.hpp>
- #include <glm/gtx/transform.hpp>
- #include <list>
- namespace scene_render_impl {
- glm::vec3 vec3_from_ptr(const float *ptr) {
- static_assert(sizeof(glm::vec3) == 3 * sizeof(float));
- return *(glm::vec3 *) ptr;
- }
- }
- using namespace scene_render_impl;
- struct scene_render::impl {
- struct actor_store_type {
- std::shared_ptr<mesh_type> model;
- actor_store_type *background = nullptr;
- float alpha_factor = 0.25f;
- bool visible = true;
- glm::mat4 transform = {};
- using material_type = mesh_info_type::material_type;
- material_type material = {};
- mesh_info_type get_mesh_info() const {
- return {.mesh = model.get(),
- .transform = transform, .material = material};
- }
- };
- bool enable_light_follow_camera = false;
- glm::vec3 light_direction = {1.0f, 0.0f, 0.0f};
- float camera_fov = 60.0f; // in degree
- float camera_near = 0.1f, camera_far = 1000.0f;
- glm::mat4 camera_transform = {};
- std::list<actor_store_type> actor_list;
- void *create_actor(const char *model_path, void *bg_actor) {
- auto &actor = actor_list.emplace_back();
- actor.model = mesh_type::create({.path = model_path});
- actor.background = (actor_store_type *) bg_actor;
- return &actor;
- }
- void draw() {
- auto info = mesh_render_info();
- info.camera.transform = camera_transform;
- float aspect = query_viewport_size().aspectRatio();
- info.camera.project = glm::perspective(camera_fov, aspect, camera_near, camera_far);
- if (enable_light_follow_camera) {
- auto camera_rot = glm::inverse(glm::mat3{camera_transform});
- light_direction = -glm::column(camera_rot, 2);
- }
- info.light.direction = light_direction;
- for (const auto &actor: actor_list) {
- if (!actor.visible) continue;
- info.model = actor.get_mesh_info();
- if (actor.background == nullptr) { // no background
- info.mode = MESH_NORMAL;
- render_mesh(info);
- } else { // with background
- info.mode = MESH_DEPTH_ALPHA;
- auto &ext = info.extra.depth_alpha;
- ext.bg = actor.background->get_mesh_info();
- ext.alpha_factor = actor.alpha_factor;
- ext.show_bg = false;
- render_mesh(info);
- }
- }
- }
- };
- scene_render::scene_render()
- : pimpl(std::make_unique<impl>()) {}
- scene_render::~scene_render() = default;
- void *scene_render::create_actor(const char *model_path, void *bg_actor) {
- return pimpl->create_actor(model_path, bg_actor);
- }
- void scene_render::set_actor_visibility(void *actor, bool visible) {
- auto real_ptr = (impl::actor_store_type *) actor;
- real_ptr->visible = visible;
- }
- void scene_render::set_actor_color(void *actor, const float *color, float ambient_factor) {
- auto real_ptr = (impl::actor_store_type *) actor;
- auto color_vec = vec3_from_ptr(color);
- real_ptr->material.diffuse = color_vec;
- real_ptr->material.ambient = ambient_factor * color_vec;
- }
- void scene_render::set_actor_alpha_factor(void *actor, float alpha_factor) {
- auto real_ptr = (impl::actor_store_type *) actor;
- real_ptr->alpha_factor = alpha_factor;
- }
- void scene_render::set_actor_transform(void *actor, glm::mat4 transform) {
- auto real_ptr = (impl::actor_store_type *) actor;
- real_ptr->transform = transform;
- }
- void scene_render::set_light_direction(glm::vec3 direction) {
- pimpl->light_direction = direction;
- }
- void scene_render::set_light_follow_camera(bool enable) {
- pimpl->enable_light_follow_camera = enable;
- }
- void scene_render::set_camera_fov(float fov) {
- pimpl->camera_fov = fov;
- }
- void scene_render::set_camera_clip_range(float near, float far) {
- pimpl->camera_near = near;
- pimpl->camera_far = far;
- }
- void scene_render::set_camera_transform(glm::mat4 transform) {
- static constexpr auto default_focal_length = 8.0f; // 8mm
- auto trans_part = glm::vec3(transform[3]);
- auto rot_part = glm::mat3(transform);
- auto focal_point = trans_part + rot_part[2] * default_focal_length;
- auto view_up = -rot_part[1];
- auto view_mat = glm::lookAt(trans_part, focal_point, view_up);
- pimpl->camera_transform = view_mat;
- }
- void scene_render::render() {
- pimpl->draw();
- }
|