Commit 2d9a78c1 authored by Andrew Wilson's avatar Andrew Wilson
Browse files

ENH: Lights properties can change at runtime, attenuation added

parent 3029be02
......@@ -36,12 +36,14 @@
#include "imstkSimulationManager.h"
#include "imstkSurfaceMesh.h"
#include "imstkVTKViewer.h"
#include "imstkSpotLight.h"
using namespace imstk;
///
/// \brief This example demonstrates controlling the camera
/// using external device. NOTE: Requires GeoMagic Touch device
/// \brief This example demonstrates controlling the camera using external
/// device. Attached is a spotlight. One could use RigidBodyController with
/// virtual coupling if they wanted damping/smoothness
///
int
main()
......@@ -53,8 +55,9 @@ main()
imstkNew<Scene> scene("CameraController");
// Device Server
imstkNew<HapticDeviceManager> server;
std::shared_ptr<HapticDeviceClient> client = server->makeDeviceClient();
imstkNew<HapticDeviceManager> server;
server->setSleepDelay(1.0);
std::shared_ptr<HapticDeviceClient> deviceClient = server->makeDeviceClient();
// Load Mesh
auto mesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/asianDragon/asianDragon.obj");
......@@ -71,26 +74,31 @@ main()
// Update Camera position
scene->getActiveCamera()->setPosition(Vec3d(0.0, 0.0, 10.0));
imstkNew<CameraController> camController(scene->getActiveCamera(), client);
//camController->setTranslationScaling(100);
//LOG(INFO) << camController->getTranslationOffset(); // should be the same than initial cam position
imstkNew<CameraController> camController(scene->getActiveCamera(), deviceClient);
camController->setTranslationScaling(0.5);
scene->addController(camController);
// Light
imstkNew<DirectionalLight> light;
light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
imstkNew<SpotLight> light;
light->setFocalPoint(Vec3d(0.0, 0.0, 0.0));
light->setPosition(Vec3d(0.0, 10.0, 0.0));
light->setIntensity(1.0);
light->setSpotAngle(10.0);
//light->setAttenuationValues(0.0, 0.0, 1.0); // Constant
//light->setAttenuationValues(0.0, 0.5, 0.0); // Linear falloff
light->setAttenuationValues(0.01, 0.0, 0.0); // Quadratic
scene->addLight("light0", light);
// Run the simulation
{
// Setup a viewer to render
imstkNew<VTKViewer> viewer("Viewer 1");
imstkNew<VTKViewer> viewer("Viewer");
viewer->setActiveScene(scene);
// Setup a scene manager to advance the scene
imstkNew<SceneManager> sceneManager("Scene Manager 1");
imstkNew<SceneManager> sceneManager("Scene Manager");
sceneManager->setActiveScene(scene);
sceneManager->setExecutionType(Module::ExecutionType::ADAPTIVE);
// attach the camera controller to the viewer
viewer->addControl(camController);
......@@ -99,6 +107,7 @@ main()
driver->addModule(server);
driver->addModule(viewer);
driver->addModule(sceneManager);
driver->setDesiredDt(0.001);
// Add mouse and keyboard controls to the viewer
{
......@@ -112,6 +121,34 @@ main()
viewer->addControl(keyControl);
}
// Change the spot angle when haptic button is pressed
connect<ButtonEvent>(deviceClient, &HapticDeviceClient::buttonStateChanged,
[&](ButtonEvent* e)
{
if (e->m_buttonState == BUTTON_PRESSED)
{
if (e->m_button == 0)
{
light->setSpotAngle(light->getSpotAngle() + 5.0);
}
else if (e->m_button == 1)
{
light->setSpotAngle(light->getSpotAngle() - 5.0);
}
}
});
// Manually make the light follow the camera controller
connect<Event>(sceneManager, &SceneManager::postUpdate,
[&](Event*)
{
const Vec3d pos = camController->getPosition();
const Quatd orientation = camController->getRotation();
light->setPosition(pos);
light->setFocalPoint(pos - orientation.toRotationMatrix().col(2));
});
driver->start();
}
......
......@@ -132,7 +132,7 @@ main()
// Light (white)
imstkNew<DirectionalLight> whiteLight;
whiteLight->setDirection(Vec3d(0.0, -8.0, 5.0));
whiteLight->setDirection(Vec3d(0.0, -8.0, -5.0));
whiteLight->setIntensity(1.0);
scene->addLight("whiteLight", whiteLight);
......
......@@ -84,74 +84,67 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
// Lights and light actors
for (const auto& light : scene->getLights())
{
// Create lights specified in the scene
switch (light->getType())
std::string name = light->getTypeName();
if (name == "DirectionalLight")
{
case imstk::LightType::Directional:
{
auto m_vtkLight = vtkSmartPointer<vtkLight>::New();
m_vtkLight->SetPositional(false);
auto color = light->getColor();
m_vtkLight->SetColor(color.r, color.g, color.b);
m_vtkLight->SetIntensity(light->getIntensity());
m_vtkLight->SetFocalPoint(light->getFocalPoint().data());
m_vtkLights.push_back(m_vtkLight);
auto lightVtk = vtkSmartPointer<vtkLight>::New();
lightVtk->SetPositional(false);
const Color& color = light->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(light->getIntensity());
lightVtk->SetFocalPoint(light->getFocalPoint().data());
lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
m_vtkLights.push_back(VtkLightPair(light, lightVtk));
}
break;
case imstk::LightType::Spot:
else if (name == "SpotLight")
{
auto m_vtkLight = vtkSmartPointer<vtkLight>::New();
m_vtkLight->SetPositional(true);
auto color = light->getColor();
m_vtkLight->SetColor(color.r, color.g, color.b);
m_vtkLight->SetIntensity(light->getIntensity());
m_vtkLight->SetFocalPoint(light->getFocalPoint().data());
auto lightVtk = vtkSmartPointer<vtkLight>::New();
lightVtk->SetPositional(true);
const Color& color = light->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(light->getIntensity());
lightVtk->SetFocalPoint(light->getFocalPoint().data());
auto spotLight = std::dynamic_pointer_cast<SpotLight>(light);
m_vtkLight->SetConeAngle(spotLight->getConeAngle());
m_vtkLight->SetPosition(spotLight->getPosition().data());
m_vtkLight->SetConeAngle(spotLight->getSpotAngle());
lightVtk->SetPosition(spotLight->getPosition().data());
lightVtk->SetConeAngle(spotLight->getSpotAngle());
lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
m_vtkLights.push_back(m_vtkLight);
m_vtkLights.push_back(VtkLightPair(light, lightVtk));
auto lightActorSpot = vtkSmartPointer<vtkLightActor>::New();
lightActorSpot->SetLight(m_vtkLight);
lightActorSpot->SetLight(lightVtk);
m_debugVtkActors.push_back(lightActorSpot);
}
break;
case imstk::LightType::Point:
else if (name == "PointLight")
{
auto m_vtkLight = vtkSmartPointer<vtkLight>::New();
m_vtkLight->SetPositional(true);
auto color = light->getColor();
m_vtkLight->SetColor(color.r, color.g, color.b);
m_vtkLight->SetIntensity(light->getIntensity());
m_vtkLight->SetFocalPoint(light->getFocalPoint().data());
auto lightVtk = vtkSmartPointer<vtkLight>::New();
lightVtk->SetPositional(true);
const Color& color = light->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(light->getIntensity());
lightVtk->SetFocalPoint(light->getFocalPoint().data());
lightVtk->SetAttenuationValues(light->getAttenuationValues().data());
auto pointLight = std::dynamic_pointer_cast<PointLight>(light);
m_vtkLight->SetConeAngle(pointLight->getConeAngle());
m_vtkLight->SetPosition(pointLight->getPosition().data());
lightVtk->SetPosition(pointLight->getPosition().data());
m_vtkLights.push_back(m_vtkLight);
m_vtkLights.push_back(VtkLightPair(light, lightVtk));
auto lightActorPoint = vtkSmartPointer<vtkLightActor>::New();
lightActorPoint->SetLight(m_vtkLight);
lightActorPoint->SetLight(lightVtk);
m_debugVtkActors.push_back(lightActorPoint);
}
break;
default:
else
{
LOG(WARNING) << "Light type undefined!";
}
}
for (const auto& light : m_vtkLights)
{
m_vtkRenderer->AddLight(light);
m_vtkRenderer->AddLight(light.second);
}
// Global Axis
......@@ -268,7 +261,7 @@ VTKRenderer::setMode(const Renderer::Mode mode, const bool enableVR)
this->addActors(m_objectVtkActors);
for (const auto& light : m_vtkLights)
{
m_vtkRenderer->AddLight(light);
m_vtkRenderer->AddLight(light.second);
}
}
}
......@@ -279,7 +272,7 @@ VTKRenderer::setMode(const Renderer::Mode mode, const bool enableVR)
this->addActors(m_objectVtkActors);
for (const auto& light : m_vtkLights)
{
m_vtkRenderer->AddLight(light);
m_vtkRenderer->AddLight(light.second);
}
}
else if (m_currentMode == Mode::Debug)
......@@ -434,6 +427,46 @@ VTKRenderer::updateRenderDelegates()
{
delegate->update();
}
// Update all lights (we don't use render delegates for these as there usually aren't
// all that many lights)
for (auto light : m_vtkLights)
{
std::shared_ptr<Light> lightImstk = light.first;
vtkSmartPointer<vtkLight> lightVtk = light.second;
std::string lightName = lightImstk->getTypeName();
if (lightName == "DirectionalLight")
{
const Color& color = lightImstk->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(lightImstk->getIntensity());
lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
}
else if (lightName == "SpotLight")
{
const Color& color = lightImstk->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(lightImstk->getIntensity());
lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
auto spotLight = std::dynamic_pointer_cast<SpotLight>(lightImstk);
lightVtk->SetPosition(spotLight->getPosition().data());
lightVtk->SetConeAngle(spotLight->getSpotAngle());
lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
}
else if (lightName == "PointLight")
{
const Color& color = lightImstk->getColor();
lightVtk->SetColor(color.r, color.g, color.b);
lightVtk->SetIntensity(lightImstk->getIntensity());
lightVtk->SetFocalPoint(lightImstk->getFocalPoint().data());
lightVtk->SetAttenuationValues(lightImstk->getAttenuationValues().data());
auto pointLight = std::dynamic_pointer_cast<PointLight>(lightImstk);
lightVtk->SetPosition(pointLight->getPosition().data());
}
}
}
void
......
......@@ -46,11 +46,12 @@ class vtkTable;
namespace imstk
{
class Camera;
class Light;
class Scene;
class SceneObject;
class Camera;
class VTKRenderDelegate;
class VisualModel;
class VTKRenderDelegate;
///
/// \class VTKRenderer
......@@ -195,7 +196,8 @@ protected:
vtkSmartPointer<vtkCamera> m_camera;
// lights
std::vector<vtkSmartPointer<vtkLight>> m_vtkLights;
using VtkLightPair = std::pair<std::shared_ptr<Light>, vtkSmartPointer<vtkLight>>;
std::vector<VtkLightPair> m_vtkLights;
// Props to be rendered
std::vector<vtkSmartPointer<vtkProp>> m_objectVtkActors;
......
......@@ -46,21 +46,12 @@ class VisualModel;
namespace ParallelUtils { class SpinLock; }
enum class TimeSteppingPolicy
{
AsFastAsPossible,
FixedFrameRate,
RealTime
};
struct SceneConfig
{
// Initializes the scene only when it needs to frame
// Note: May cause delays to run the first frame of the scene due to scene initialization
bool lazyInitialization = false;
TimeSteppingPolicy timeStepping = TimeSteppingPolicy::AsFastAsPossible;
// Keep track of the fps for the scene
bool trackFPS = false;
......
......@@ -36,14 +36,15 @@ namespace imstk
class DirectionalLight : public Light
{
public:
DirectionalLight() : Light(LightType::Directional)
DirectionalLight()
{
this->setFocalPoint(-1.0f, -1.0f, -1.0f);
this->setFocalPoint(-1.0, -1.0, -1.0);
}
virtual ~DirectionalLight() override = default;
virtual const std::string getTypeName() const { return "DirectionalLight"; }
public:
const std::string getTypeName() const override { return "DirectionalLight"; }
///
/// \brief Direction of the light
......
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
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 "imstkLight.h"
#include "imstkLogger.h"
namespace imstk
{
void
Light::setFocalPoint(const float& x, const float& y, const float& z)
{
if (x != 0 || y != 0 || z != 0)
{
m_focalPoint = Vec3f((float)x, (float)y, (float)z);
}
else
{
LOG(WARNING) << "Directional lights can't have focal point at (0, 0, 0)";
}
}
} // imstk
......@@ -9,7 +9,7 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
......@@ -29,16 +29,6 @@
namespace imstk
{
///
/// \brief Enumeration for the type of light
///
enum class LightType
{
Directional,
Point,
Spot
};
///
/// \class Light
///
......@@ -46,26 +36,19 @@ enum class LightType
///
class Light : public SceneEntity
{
protected:
Light() = default;
public:
virtual ~Light() override = default;
public:
///
/// \brief Returns the type of light (see imstk::LightType)
///
LightType getType() const { return m_type; }
///
/// \brief Set the type of the light
///
void setType(const LightType& type) { m_type = type; }
///
/// \brief Set the light focal point
///
virtual void setFocalPoint(const Vec3d& p) { this->setFocalPoint((float)p[0], (float)p[1], (float)p[2]); }
virtual void setFocalPoint(const float& x, const float& y, const float& z);
const Vec3f getFocalPoint() const { return m_focalPoint; }
void setFocalPoint(const Vec3d& p) { m_focalPoint = p; }
void setFocalPoint(const double x, const double y, const double z) { setFocalPoint(Vec3d(x, y, z)); }
const Vec3d& getFocalPoint() const { return m_focalPoint; }
///
/// \brief Get the status (On/off) of the light
......@@ -85,7 +68,7 @@ public:
///
/// \brief Get the light color
///
const Color getColor() const { return m_color; }
const Color& getColor() const { return m_color; }
///
/// \brief Set the light color
......@@ -95,22 +78,32 @@ public:
///
/// \brief Get the light intensity
///
float getIntensity() const { return m_intensity; }
double getIntensity() const { return m_intensity; }
///
/// \brief Set the light intensity. This value is unbounded.
///
void setIntensity(const double intensity) { m_intensity = (float)intensity; }
void setIntensity(const double intensity) { m_intensity = intensity; }
protected:
Light(const LightType& type) : SceneEntity(), m_type(type) { }
///
/// \brief Sets the attenuation values. Quadratic, linear, and constant c (ax^2+bx+c)
/// (a,b,c) = {0,0,1} would be constant lighting, multiplied with intensity
///
void setAttenuationValues(const double a, const double b, const double c)
{
m_attenuation[0] = c;
m_attenuation[1] = b;
m_attenuation[2] = a;
}
// properties with defaults
float m_intensity = 1.;
Color m_color = Color::White;
bool m_switchState = true;
Vec3f m_focalPoint = Vec3f(0, 0, 0);
const Vec3d& getAttenuationValues() const { return m_attenuation; }
LightType m_type;
protected:
// properties with defaults
double m_intensity = 1.0;
Color m_color = Color::White;
bool m_switchState = true;
Vec3d m_focalPoint = Vec3d::Zero();
Vec3d m_attenuation = Vec3d(1.0, 0.0, 0.0); ///> c, b, a (ax^2+bx+c)
};
} // imstk
\ No newline at end of file
......@@ -36,48 +36,20 @@ namespace imstk
class PointLight : public Light
{
public:
///
/// \brief Constructors
///
PointLight(const LightType& type = LightType::Point) : Light(type) { }
PointLight() = default;
virtual ~PointLight() override = default;
public:
virtual const std::string getTypeName() const { return "PointLight"; }
///
/// \brief Get the cone angle
///
const float getConeAngle() const { return m_coneAngle; }
///
/// \brief Get the light position
///
void setConeAngle(const double angle) { m_coneAngle = (float)angle; }
const std::string getTypeName() const override { return "PointLight"; }
///
/// \brief Get the light position
///
const Vec3f getPosition() const { return m_position; }
///
/// \brief Set the light position
///
void setPosition(const Vec3d& p)
{
m_position = Vec3f(
static_cast<float>(p[0]),
static_cast<float>(p[1]),
static_cast<float>(p[2]));
};
void setPosition(const double& x, const double& y, const double& z)
const Vec3d getPosition() const { return m_position; }
void setPosition(const Vec3d& p) { m_position = p; }
void setPosition(const double x, const double y, const double z)
{
this->setPosition(Vec3d(x, y, z));
}
protected:
Vec3f m_position = Vec3f(0.0f, 0.0f, 0.0f);
float m_coneAngle = 179.0f;
Vec3d m_position = Vec3d::Zero();
};
} // imstk
\ No newline at end of file
......@@ -23,8 +23,6 @@
#include "imstkPointLight.h"
#include <string>
namespace imstk
{
///
......@@ -35,30 +33,23 @@ namespace imstk
class SpotLight : public PointLight
{
public:
///
/// \brief Constructors
///
SpotLight() : PointLight(LightType::Spot)
{
m_coneAngle = 10.0f;
}
SpotLight() : m_spotAngle(10.0) { }
virtual ~SpotLight() override = default;
public:
virtual const std::string getTypeName() const { return "SpotLight"; }
const std::string getTypeName() const override { return "SpotLight"; }
///