Skip to content
Snippets Groups Projects
Select Git revision
  • 60c37c758b0ad491f8e63d7866e3a6094317bf84
  • stable default protected
  • MA_Pape_2018
  • MA_2018_Lopatin
  • feature/mesh_viewer
  • feature/#468_access_isosurface_scalar
  • feature/#459_default_primitives
  • master protected
  • feature/#470_Create_a_color_lookup_table
  • feature/#473_resize_companion_window
  • feature/#462_do_not_use_arb_extensions
  • feature/#495_Provide_data_for_larger_isosurfaces
  • feature/#323_default_image
  • feature/#480_Create_a_smaller_test_mesh_for_combustion_demo
  • feature/#236_Get_Integration_tests_running_on_CI
  • feature/#447_Copy_standard_assets_to_build_folder
  • 447-copy-standard-assets-to-build-folder-and-remove-resource-path
  • feature/#445_mesh_render_settings_component
  • feature/#251_Make_sure_tests_cpp_is_compiled_once
  • feature/#455_Remove_navigation_and_improve_interaction_for_combustion_demo
  • feature/446_strange_txt_files
  • v18.06.0
  • v18.05.0
  • #251_bad
  • #251_good
  • v18.03.0
  • v18.02.0
  • v18.01.0
  • v17.12.0
  • v17.11.0
  • v17.10.0
  • v17.09.0
  • v17.07.0
33 results

lens.cpp

Blame
  • lens.cpp 14.10 KiB
    //------------------------------------------------------------------------------
    // Project Phoenix
    //
    // Copyright (c) 2017-2018 RWTH Aachen University, Germany,
    // Virtual Reality & Immersive Visualization Group.
    //------------------------------------------------------------------------------
    //                                 License
    //
    // Licensed under the 3-Clause BSD License (the "License");
    // you may not use this file except in compliance with the License.
    // See the file LICENSE for the full text.
    // You may obtain a copy of the License at
    //
    //     https://opensource.org/licenses/BSD-3-Clause
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    //------------------------------------------------------------------------------
    
    #include "lens.hpp"
    #include <optix.h>
    #include "object_manager.hpp"
    #include "optix_context_manager.hpp"
    
    #include "phx/rendering/components/transform.hpp"
    #include "selection_mark_handler.hpp"
    #include "selector.hpp"
    
    #include "phx/rendering/components/material_handle.hpp"
    #include "phx/resources/resource_pointer.hpp"
    #include "phx/resources/resource_utils.hpp"
    #include "phx/resources/types/material.hpp"
    #include "phx/resources/types/model.hpp"
    #include "phx/suppress_warnings.hpp"
    
    SUPPRESS_WARNINGS_BEGIN
    #include "glm/glm.hpp"
    #include "glm/gtx/rotate_vector.hpp"
    #include "glm/gtx/string_cast.hpp"
    SUPPRESS_WARNINGS_END
    
    Lens::Lens(phx::Engine* engine, phx::Scene* scene, OptixContextManager* manager,
               LensSideType type1, LensSideType type2, optix::float3 frontCenter,
               float lensradius, float thickness, float radius, float radius2) {
      manager_ = manager;
      scene_ = scene;
    
      CreateGlassMaterialInstance();
      geometry_ = manager->GetContext()->createGeometryInstance(
          manager->GetLensGeometry(), &glass_material_, &glass_material_ + 1);
    
      geometry_["center"]->setFloat(0, 0, 0);
      geometry_["radius"]->setFloat(radius);
      geometry_["radius2"]->setFloat(radius2);
      geometry_["orientation"]->setFloat(optix::make_float3(0.f, 0.f, -1.f));
      geometry_["lensRadius"]->setFloat(lensradius);
    
      geometry_["side1Type"]->setInt(type1);
      geometry_["side2Type"]->setInt(type2);
      type_1_ = type1;
      type_2_ = type2;
    
      float cylinderLength = GetCylinderLength(thickness);
      geometry_["halfCylinderLength"]->setFloat(cylinderLength / 2);
    
      transform_ = manager->GetContext()->createTransform();
      transform_->setMatrix(false, &glm::mat4()[0][0], &glm::mat4()[0][0]);
      // Add the lens to the scene
    
      geometry_group_ = manager->GetContext()->createGeometryGroup();
      geometry_group_->addChild(geometry_);
      acceleration_structure_ = manager->GetContext()->createAcceleration("Trbvh");
      acceleration_structure_->setProperty("refit", "1");
    
      geometry_group_->setAcceleration(acceleration_structure_);
    
      transform_->setChild<optix::GeometryGroup>(geometry_group_);
      manager->GetTopObject()->addChild(transform_);
    
      // Attach handles
      entity_ = scene->CreateEntity();
      auto center =
          frontCenter - optix::make_float3(0.f, 0.f, -1.f) * thickness / 2;
      entity_->AddComponent<phx::Transform>()->Translate(
          glm::vec3(center.x, center.y, center.z));
      selector_ = entity_->AddComponent<phx::Selector>(nullptr, true);
    
      support_rod_ = new SupportRod(scene, selector_, false);
    
      auto obj_m = engine->GetSystem<ObjectManager>();
    
      // Set Moving
      selector_->SetMove([this, obj_m](phx::Transform* t, glm::mat4 r) {
        auto pos = glm::vec3((t->GetGlobalMatrix() * r)[3]);
        auto pos_proj =
            glm::dot(pos - obj_m->GetCenterAxisPos(), glm::vec3(0, 0, 1)) *
                glm::vec3(0, 0, 1) +
            obj_m->GetCenterAxisPos();
    
        // close enough? Then snap!
        if (glm::length(pos - pos_proj) <= obj_m->GetSnapDistance()) pos = pos_proj;
    
        entity_->GetFirstComponent<phx::Transform>()->SetGlobalTranslation(pos);
        glm::mat4 trans =
            entity_->GetFirstComponent<phx::Transform>()->GetGlobalMatrix();
        transform_->setMatrix(true, &(trans[0][0]), &(inverse(trans)[0][0]));
    
        support_rod_->Moved();
        acceleration_structure_->markDirty();
        manager_->TopAccelerationMarkDirty();
      });
      selector_->SetExternalUpdate([this]() {
        glm::mat4 trans =
            entity_->GetFirstComponent<phx::Transform>()->GetGlobalMatrix();
        transform_->setMatrix(true, &(trans[0][0]), &(inverse(trans)[0][0]));
    
        support_rod_->Moved();
        acceleration_structure_->markDirty();
        manager_->TopAccelerationMarkDirty();
      });
    
      // Store if grabbed
      selector_->SetGrab([this](phx::Transform*, glm::mat4) { grabbed_ = true; });
      selector_->SetRelease([this]() { grabbed_ = false; });
    
      RecalculateBoundingBox();
      acceleration_structure_->markDirty();
      manager_->TopAccelerationMarkDirty();
    }
    
    Lens::~Lens() {
      manager_->GetTopObject()->removeChild(transform_);
      glass_material_->destroy();
      geometry_->destroy();
      geometry_group_->destroy();
      transform_->destroy();
      acceleration_structure_->destroy();
      scene_->RemoveEntity(entity_);
      delete support_rod_;
      manager_->TopAccelerationMarkDirty();
    }
    
    void Lens::NextLensSideType1() {
      auto s1 = geometry_["side1Type"]->getInt();
      auto s2 = geometry_["side2Type"]->getInt();
    
      s1 = (((s1 + 1) + 1) % 3) - 1;
    
      SetLensSideTypes(static_cast<LensSideType>(s1),
                       static_cast<LensSideType>(s2));
    }
    
    void Lens::PreviousLensSideType1() {
      auto s1 = geometry_["side1Type"]->getInt();
      auto s2 = geometry_["side2Type"]->getInt();
    
      s1 = (((s1 - 1 + 3) + 1) % 3) - 1;
    
      SetLensSideTypes(static_cast<LensSideType>(s1),
                       static_cast<LensSideType>(s2));
    }
    
    void Lens::NextLensSideType2() {
      auto s1 = geometry_["side1Type"]->getInt();
      auto s2 = geometry_["side2Type"]->getInt();
    
      s2 = (((s2 + 1) + 1) % 3) - 1;
    
      SetLensSideTypes(static_cast<LensSideType>(s1),
                       static_cast<LensSideType>(s2));
    }
    
    void Lens::PreviousLensSideType2() {
      auto s1 = geometry_["side1Type"]->getInt();
      auto s2 = geometry_["side2Type"]->getInt();
    
      s2 = (((s2 - 1 + 3) + 1) % 3) - 1;
    
      SetLensSideTypes(static_cast<LensSideType>(s1),
                       static_cast<LensSideType>(s2));
    }
    
    void Lens::NextGlassType() {
      glass_type_ = static_cast<GlassType>((glass_type_ + 1) % 5);
      ChangedWaveLength(current_wavelength_nm_);
    }
    
    void Lens::PreviousGlassType() {
      glass_type_ = static_cast<GlassType>((glass_type_ - 1 + 5) % 5);
      ChangedWaveLength(current_wavelength_nm_);
    }
    
    std::string Lens::GetLensTypeName1() {
      return GetTypeString(
          static_cast<LensSideType>(geometry_["side1Type"]->getInt()));
    }
    
    std::string Lens::GetLensTypeName2() {
      return GetTypeString(
          static_cast<LensSideType>(geometry_["side2Type"]->getInt()));
    }
    
    std::string Lens::GetGlassTypeName() {
      switch (glass_type_) {
        case BK7:
          return "BK7";
        case SF5:
          return "SF5";
        case SF11:
          return "SF11";
        case FUSED_SILICA:
          return "Fus.Sil.";
        case SK16:
          return "SK16";
        case F2:
          return "F2";
      }
      return "Unknown";
    }
    
    void Lens::Translate(glm::vec3 pos) {
      GetEntity()->GetFirstComponent<phx::Transform>()->SetGlobalTranslation(pos);
      selector_->ExternalUpdate();
    }
    
    void Lens::SetSelected(bool s) { support_rod_->SetMarked(s); }
    
    void Lens::ChangedWaveLength(float wavelength_nm) {
      double wl2 = glm::pow(wavelength_nm / 1000.0, 2);
      float index = (float)sqrt(1 +
                                (glass_definitions[glass_type_][0].x * wl2) /
                                    (wl2 - glass_definitions[glass_type_][1].x) +
                                (glass_definitions[glass_type_][0].y * wl2) /
                                    (wl2 - glass_definitions[glass_type_][1].y) +
                                (glass_definitions[glass_type_][0].z * wl2) /
                                    (wl2 - glass_definitions[glass_type_][1].z));
    
      glass_material_["refraction_index"]->setFloat(index);
      current_wavelength_nm_ = wavelength_nm;
    }
    
    std::array<glm::vec3, 2u> Lens::ComputeAABBFromCylinder(glm::vec3 orientation,
                                                            float halfLength1,
                                                            float halfLength2,
                                                            float radius) {
      auto res = std::array<glm::vec3, 2u>();
    
      glm::vec3 sideVector =
          normalize(cross(orientation, glm::vec3(0.0f, 1.0f, 0.0f)));
      glm::vec3 newUp = normalize(cross(sideVector, orientation));
      sideVector = sideVector * radius;
      newUp = newUp * radius;
      glm::vec3 depthVector = normalize(orientation);
    
      res[0] = glm::vec3(INFINITY);
      res[1] = glm::vec3(-INFINITY);
      glm::vec3 testVector = glm::vec3(0.0f);
    
      testVector = depthVector * halfLength1 + sideVector + newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = depthVector * halfLength1 + sideVector - newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = depthVector * halfLength1 - sideVector + newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = depthVector * halfLength1 - sideVector - newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
    
      testVector = -depthVector * halfLength2 + sideVector + newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = -depthVector * halfLength2 + sideVector - newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = -depthVector * halfLength2 - sideVector + newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
      testVector = -depthVector * halfLength2 - sideVector - newUp;
      res[1] = glm::max(res[1], testVector);
      res[0] = glm::min(res[0], testVector);
    
      return res;
    }
    
    glm::vec3 Lens::GetFrontCenter() {
      return entity_->GetFirstComponent<phx::Transform>()->GetGlobalTranslation() +
             glm::mat3(
                 entity_->GetFirstComponent<phx::Transform>()->GetGlobalMatrix()) *
                 glm::vec3(0.f, 0.f, -1.f) * GetThickness() / 2.0f;
    }
    
    glm::vec2 Lens::GetRotation() {
      auto mat = entity_->GetFirstComponent<phx::Transform>()->GetGlobalMatrix();
      glm::vec3 up = normalize(glm::mat3(mat) * glm::vec3(0, 1, 0));
      glm::vec3 right = normalize(glm::mat3(mat) * glm::vec3(1, 0, 0));
    
      float angle_horizontal = -glm::atan(right.z, right.x);
      auto position_YZ = glm::rotateY(up, -angle_horizontal);
      float angle_vertical =
          -glm::atan(position_YZ.y, position_YZ.z) + glm::pi<float>() / 2;
    
      return glm::vec2(angle_horizontal, angle_vertical);
    }
    
    float Lens::GetCylinderLength(float thickness) {
      float lr = geometry_["lensRadius"]->getFloat();
      float r1 = geometry_["radius"]->getFloat();
      float r2 = geometry_["radius2"]->getFloat();
    
      // thickness of the halfspheres
      float halfThickness1 = r1 - sqrtf(-lr * lr + r1 * r1);
      if (type_1_ == CONCAVE) halfThickness1 *= -1;
      if (type_1_ == PLANE) halfThickness1 = 0;
    
      float halfThickness2 = r2 - sqrtf(-lr * lr + r2 * r2);
      if (type_2_ == CONCAVE) halfThickness2 *= -1;
      if (type_2_ == PLANE) halfThickness2 = 0;
    
      return thickness - halfThickness1 - halfThickness2;
    }
    
    float Lens::GetThickness(float cylinder_length) {
      float lr = geometry_["lensRadius"]->getFloat();
      float r1 = geometry_["radius"]->getFloat();
      float r2 = geometry_["radius2"]->getFloat();
    
      // thickness of the halfspheres
      float halfThickness1 = r1 - sqrtf(-lr * lr + r1 * r1);
      if (type_1_ == CONCAVE) halfThickness1 *= -1;
      if (type_1_ == PLANE) halfThickness1 = 0;
    
      float halfThickness2 = r2 - sqrtf(-lr * lr + r2 * r2);
      if (type_2_ == CONCAVE) halfThickness2 *= -1;
      if (type_2_ == PLANE) halfThickness2 = 0;
    
      return cylinder_length + halfThickness1 + halfThickness2;
    }
    
    void Lens::SetLensSideTypes(LensSideType type1, LensSideType type2) {
      float thickness =
          GetThickness(geometry_["halfCylinderLength"]->getFloat() * 2);
    
      geometry_["side1Type"]->setInt(type1);
      geometry_["side2Type"]->setInt(type2);
    
      type_1_ = type1;
      type_2_ = type2;
    
      geometry_["halfCylinderLength"]->setFloat(GetCylinderLength(thickness) / 2);
    
      MarkDirty();
    }
    
    void Lens::RecalculateBoundingBox() {
      auto o = geometry_["orientation"]->getFloat3();
      float hc = geometry_["halfCylinderLength"]->getFloat();
      float lr = geometry_["lensRadius"]->getFloat();
    
      float r1 = geometry_["radius"]->getFloat();
      float r2 = geometry_["radius2"]->getFloat();
    
      // thickness of the halfspheres
      float halfThickness1 = r1 - sqrtf(-lr * lr + r1 * r1);
      if (type_1_ == PLANE || type_1_ == CONCAVE) halfThickness1 = 0;
      float halfThickness2 = r2 - sqrtf(-lr * lr + r2 * r2);
      if (type_2_ == PLANE || type_2_ == CONCAVE) halfThickness2 = 0;
    
      auto bb = ComputeAABBFromCylinder(
          glm::vec3(o.x, o.y, o.z), hc + halfThickness1, hc + halfThickness2, lr);
      selector_->SetCollider(bb[0], bb[1]);
      selector_->ExternalUpdate();
    }
    
    std::string Lens::GetTypeString(LensSideType t) {
      switch (t) {
        case CONCAVE:
          return "Concave";
        case CONVEX:
          return "Convex";
        case PLANE:
          return "Plane";
      }
      return "Unknown";
    }
    
    void Lens::CreateGlassMaterialInstance() {
      glass_material_ = manager_->GetContext()->createMaterial();
      glass_material_->setClosestHitProgram(0,
                                            manager_->GetGlassProgramPerspective());
      glass_material_->setClosestHitProgram(1,
                                            manager_->GetGlassProgramIterative());
    
      glass_material_["importance_cutoff"]->setFloat(1e-2f);
      glass_material_["cutoff_color"]->setFloat(0.035f, 0.102f, 0.169f);
      glass_material_["fresnel_exponent"]->setFloat(3.0f);
      glass_material_["fresnel_minimum"]->setFloat(0.1f);
      glass_material_["fresnel_maximum"]->setFloat(1.0f);
      glass_material_["refraction_index"]->setFloat(1.4f);
      glass_material_["refraction_color"]->setFloat(1.0f, 1.0f, 1.0f);
      glass_material_["reflection_color"]->setFloat(1.0f, 1.0f, 1.0f);
      glass_material_["refraction_maxdepth"]->setInt(10);
      glass_material_["reflection_maxdepth"]->setInt(5);
      glass_material_["extinction_constant"]->setFloat(log(0.83f), log(0.83f),
                                                       log(0.83f));
    }