Commit 6e79fb81 authored by Andrew Wilson's avatar Andrew Wilson
Browse files

ENH: Textures can be init'd from ImageData, they can be modified at runtime,...

ENH: Textures can be init'd from ImageData, they can be modified at runtime, you can also swap textures
parent 4ea441e4
fa74749d09dd8c7e7cd76dbff65bed64fc0ea61bee40b8d6b65f35d6bdd3350d4600799af508dd4d6123498f1729c6ee13bcfbe42ec9b9c5576629a089728d98
\ No newline at end of file
8ddf23fb3bfcda140bcdc26b49347f28a842d3336c1b4f4437a63639d5ade9d4db73e2de5361856aad131cede31f8df3d28072077e4de83ef7081a886fb231be
\ No newline at end of file
a4bd2738dc5bb185cd4cce6458f0fac4f8c67efe921cc71b98cc8c95d177d44841a890906e89a08ba1a5a58dc1d92c225151fdd58ac5d47e83485d66e9a1fe97
\ No newline at end of file
b4524aebc410ac8942a2936ccba69f2b8bd35260ada2a21ca1ea138445235ebbba42486ff4816b40c70e7f0cd58b948e547326686f13e971aad045d014db75f2
\ No newline at end of file
da3daa5b9e89bffcd56014daa8f697c0d81022e81bbff6cc0641558ece7f7a55fc1c33cfc6ce61262f8bd31962e456c5e8c36f0043aa4cbce455c59450a048da
\ No newline at end of file
a4bd2738dc5bb185cd4cce6458f0fac4f8c67efe921cc71b98cc8c95d177d44841a890906e89a08ba1a5a58dc1d92c225151fdd58ac5d47e83485d66e9a1fe97
\ No newline at end of file
2a17cde9cd940ae593d0fb3d5719dfe15df9afef993a7a7f28b7002ac799eff901c039838a41717eab9767c1bcd3a983ba9b5c1fd9e4a8717a486c5b2236b496
\ No newline at end of file
......@@ -20,10 +20,12 @@
=========================================================================*/
#include "imstkCamera.h"
#include "imstkImageData.h"
#include "imstkKeyboardDeviceClient.h"
#include "imstkKeyboardSceneControl.h"
#include "imstkLight.h"
#include "imstkLogger.h"
#include "imstkMeshIO.h"
#include "imstkMouseSceneControl.h"
#include "imstkNew.h"
#include "imstkPbdModel.h"
......@@ -35,11 +37,31 @@
#include "imstkSurfaceMesh.h"
#include "imstkVisualModel.h"
#include "imstkVTKViewer.h"
#include "imstkMeshIO.h"
#include "imstkImageData.h"
using namespace imstk;
static void
setFabricTextures(std::shared_ptr<RenderMaterial> material)
{
auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricDiffuse.jpg");
material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricNormal.jpg");
material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricORM.jpg");
material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
}
static void
setFleshTextures(std::shared_ptr<RenderMaterial> material)
{
auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshDiffuse.jpg");
material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshNormal.jpg");
material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshORM.jpg");
material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
}
///
/// \brief Creates cloth geometry
/// \param cloth width
......@@ -51,7 +73,8 @@ static std::shared_ptr<SurfaceMesh>
makeClothGeometry(const double width,
const double height,
const int nRows,
const int nCols)
const int nCols,
const double uvScale)
{
imstkNew<SurfaceMesh> clothMesh;
......@@ -99,7 +122,7 @@ makeClothGeometry(const double width,
{
for (int j = 0; j < nCols; j++)
{
uvCoords[i * nCols + j] = Vec2f(static_cast<float>(i) / nRows, static_cast<float>(j) / nCols);
uvCoords[i * nCols + j] = Vec2f(static_cast<float>(i) / nRows, static_cast<float>(j) / nCols) * uvScale;
}
}
......@@ -127,7 +150,7 @@ makeClothObj(const std::string& name,
imstkNew<PbdObject> clothObj(name);
// Setup the Geometry
std::shared_ptr<SurfaceMesh> clothMesh = makeClothGeometry(10.0, 10.0, 16, 16);
std::shared_ptr<SurfaceMesh> clothMesh = makeClothGeometry(10.0, 10.0, 16, 16, 2.0);
// Setup the Parameters
imstkNew<PBDModelConfig> pbdParams;
......@@ -149,12 +172,7 @@ makeClothObj(const std::string& name,
material->setBackFaceCulling(false);
material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
material->setShadingModel(RenderMaterial::ShadingModel::PBR);
material->setRoughness(0.5);
material->setMetalness(0.1);
auto imageData = MeshIO::read<ImageData>("C:/Users/Andx_/Pictures/MyTextures/carpet.jpg");
material->addTexture(std::make_shared<Texture>(imageData, Texture::Type::Diffuse));
//material->addTexture(std::make_shared<Texture>("C:/Users/Andx_/Pictures/MyTextures/carpetN.png", Texture::Type::Normal));
setFleshTextures(material);
imstkNew<VisualModel> visualModel(clothMesh);
visualModel->setRenderMaterial(material);
......@@ -217,18 +235,19 @@ main()
viewer->addControl(keyControl);
}
imstkNew<Texture> tex("C:/Users/Andx_/Pictures/MyTextures/carpetN.png", Texture::Type::Normal);
using Vec3uc = Eigen::Matrix<unsigned char, 3, 1>;
queueConnect<KeyEvent>(viewer->getKeyboardDevice(), &KeyboardDeviceClient::keyPress, sceneManager, [&](KeyEvent* e)
{
if (e->m_key == 'i')
// Set new textures
if (e->m_key == '1')
{
clothObj->getVisualModel(0)->getRenderMaterial()->addTexture(tex);
setFleshTextures(clothObj->getVisualModel(0)->getRenderMaterial());
}
else if (e->m_key == 'j')
else if (e->m_key == '2')
{
clothObj->getVisualModel(0)->getRenderMaterial()->removeTexture(tex);
setFabricTextures(clothObj->getVisualModel(0)->getRenderMaterial());
}
// Darken the texture pixel values
else if (e->m_key == 'h')
{
auto imageData = clothObj->getVisualModel(0)->getRenderMaterial()->getTexture(Texture::Type::Diffuse)->getImageData();
......@@ -240,7 +259,7 @@ main()
}
clothObj->getVisualModel(0)->getRenderMaterial()->getTexture(Texture::Type::Diffuse)->postModified();
}
});
});
driver->start();
}
......
......@@ -201,7 +201,7 @@ void
RenderMaterial::removeTexture(Texture::Type type)
{
// If the texture already has path "" then it is empty
const size_t typeInt = static_cast<size_t>(type);
const size_t typeInt = static_cast<size_t>(type);
std::shared_ptr<Texture> prevTex = m_textures[typeInt];
if (prevTex->getPath() != "")
{
......
......@@ -82,7 +82,7 @@ public:
///
/// \brief Posted when textures are modified
///
///
SIGNAL(RenderMaterial,texturesModified);
public:
......
......@@ -31,7 +31,6 @@ Texture::Texture(std::string path, Type type) :
Texture::Texture(std::shared_ptr<ImageData> imageTex, Type type) :
imageTexture(imageTex), m_type(type), m_path("")
{
}
Texture::Type
......@@ -98,12 +97,6 @@ Texture::getTypeAsString(Type type)
}
}
const std::string
Texture::getPath() const
{
return m_path;
}
const Texture::FileType
Texture::getFileType()
{
......@@ -136,22 +129,4 @@ Texture::getFileType()
return textureType;
}
bool
Texture::getMipmapsEnabled()
{
return m_mipmapsEnabled;
}
bool
Texture::isAnisotropyEnabled()
{
return m_anisotropyEnabled;
}
float
Texture::getAnisotropyFactor()
{
return m_anisotropyFactor;
}
}
\ No newline at end of file
......@@ -32,7 +32,7 @@ class ImageData;
///
/// \class Texture
///
///
/// \brief A texture can be defined by file reference or ImageData input
///
class Texture : public EventObject
......@@ -82,7 +82,7 @@ public:
/// \brief Constructor
/// \param imageTex input texture image
/// \param type Type of texture
///
///
Texture(std::shared_ptr<ImageData> imageTex, Type type = Type::Diffuse);
///
......@@ -91,7 +91,7 @@ public:
virtual ~Texture() = default;
public:
SIGNAL(Texture, modified);
SIGNAL(Texture,modified);
void postModified() { this->postEvent(Event(modified())); }
......@@ -114,7 +114,7 @@ public:
///
/// \brief Get path
///
const std::string getPath() const;
const std::string& getPath() const{ return m_path; }
///
/// \brief Get file extension
......@@ -124,20 +124,32 @@ public:
///
/// \brief Get if mipmaps are enabled
///
bool getMipmapsEnabled();
const bool getMipmapsEnabled() const{ return m_mipmapsEnabled; }
///
/// \brief Get if repeat is enabled, if off it clamps
///
const bool getRepeating() const{ return m_repeating; }
///
/// \brief Get if anisotropic filtering is enabled
///
bool isAnisotropyEnabled();
const bool isAnisotropyEnabled() const{ return m_anisotropyEnabled; }
///
/// brief Get anisotropy factor
/// \brief Get anisotropy factor
///
float getAnisotropyFactor();
const double getAnisotropyFactor() const{ return m_anisotropyFactor; }
///
/// \brief Set the input image data, not required (paths to files can be used instead)
///
void setImageData(std::shared_ptr<ImageData> imgData) { imageTexture = imgData; }
std::shared_ptr<ImageData> getImageData() const { return imageTexture; }
///
/// \brief Get the input image data for the texture, not required (paths to files can be used instead)
///
std::shared_ptr<ImageData> getImageData() const{ return imageTexture; }
protected:
std::shared_ptr<ImageData> imageTexture = nullptr;
......@@ -147,9 +159,12 @@ protected:
// Helps with texture aliasing (and a little with performance)
bool m_mipmapsEnabled = true;
// Repeating
bool m_repeating = true;
// Helps sharpen mipmapped textures at more extreme angles
bool m_anisotropyEnabled = true;
float m_anisotropyFactor = 1.0;
bool m_anisotropyEnabled = true;
double m_anisotropyFactor = 1.0;
};
}
......
......@@ -24,16 +24,16 @@
#include "imstkTexture.h"
#include "imstkTextureDelegate.h"
#include <map>
#include <unordered_map>
namespace imstk
{
///
/// \class TextureManager
///
///
/// \brief The TextureManager provides delegates for textures, it will create new ones
/// and cache old ones
///
///
template<class T>
class TextureManager
{
......@@ -41,19 +41,18 @@ static_assert(std::is_base_of<TextureDelegate, T>::value, "T isn't a subclass of
public:
///
/// \brief Add texture
/// \brief Constructor
///
std::shared_ptr<T> getTextureDelegate(std::shared_ptr<Texture> texture);
protected:
friend class VTKRenderer;
TextureManager() = default;
public:
///
/// \brief Constructor
/// \brief Add texture
///
TextureManager() = default;
std::shared_ptr<T> getTextureDelegate(std::shared_ptr<Texture> texture);
std::map<std::shared_ptr<Texture>, std::shared_ptr<T>> m_textureMap;
protected:
std::unordered_map<std::shared_ptr<Texture>, std::shared_ptr<T>> m_textureMap;
};
template<class T> std::shared_ptr<T>
......
......@@ -23,6 +23,8 @@
#include "imstkEventObject.h"
#include "imstkMacros.h"
#include "imstkTextureManager.h"
#include "imstkVTKTextureDelegate.h"
#include <vtkSmartPointer.h>
......@@ -47,6 +49,7 @@ class VTKRenderDelegate : public EventObject
public:
virtual ~VTKRenderDelegate() override = default;
public:
///
/// \brief Instantiate proper render delegate
///
......@@ -67,6 +70,11 @@ public:
///
vtkSmartPointer<vtkProp3D> getVtkActor() { return m_actor; }
///
/// \brief Set the TextureManager
///
void setTextureManager(std::weak_ptr<TextureManager<VTKTextureDelegate>> textureManager) { m_textureManager = textureManager; }
///
/// \brief Update render delegate
///
......@@ -110,5 +118,7 @@ protected:
std::shared_ptr<VisualModel> m_visualModel; ///< imstk visual model (contains data (geometry) and render specification (render material))
std::shared_ptr<RenderMaterial> m_material;
std::weak_ptr<TextureManager<VTKTextureDelegate>> m_textureManager;
};
}
......@@ -23,6 +23,8 @@
#include "imstkGeometryUtilities.h"
#include "imstkRenderMaterial.h"
#include "imstkSurfaceMesh.h"
#include "imstkTextureDelegate.h"
#include "imstkTextureManager.h"
#include "imstkVisualModel.h"
#include <vtkActor.h>
......@@ -127,6 +129,8 @@ VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate(std::shared_ptr<Visua
// When index buffer internals are modified
queueConnect<Event>(m_geometry->getVertexNormals(), &VecDataArray<double, 3>::modified, this, &VTKSurfaceMeshRenderDelegate::normalDataModified);
connect<Event>(m_material, &RenderMaterial::texturesModified, this, &VTKSurfaceMeshRenderDelegate::texturesModified);
// Setup mapper
{
vtkNew<vtkPolyDataMapper> mapper;
......@@ -250,11 +254,13 @@ VTKSurfaceMeshRenderDelegate::geometryModified(Event* imstkNotUsed(e))
void
VTKSurfaceMeshRenderDelegate::texturesModified(Event* e)
{
// If a texture is set/swapped reinit all textures
RenderMaterial* material = static_cast<RenderMaterial*>(e->m_sender);
if (material != nullptr)
{
// Reload all textures
// If texture already present, don't do anything unless name changed
initializeTextures();
}
}
......@@ -338,7 +344,7 @@ VTKSurfaceMeshRenderDelegate::setIndexBuffer(std::shared_ptr<VecDataArray<int, 3
}
void
VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelegate>& textureManager)
VTKSurfaceMeshRenderDelegate::initializeTextures()
{
auto material = m_visualModel->getRenderMaterial();
if (material == nullptr)
......@@ -349,6 +355,8 @@ VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelega
unsigned int currentUnit = 0;
// Go through all of the textures
vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(m_actor);
actor->GetProperty()->RemoveAllTextures();
for (int unit = 0; unit < (int)Texture::Type::None; unit++)
{
// Get imstk texture
......@@ -360,7 +368,8 @@ VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelega
}
// Get vtk texture
auto textureDelegate = textureManager.getTextureDelegate(texture);
std::shared_ptr<TextureManager<VTKTextureDelegate>> textureManager = m_textureManager.lock();
auto textureDelegate = textureManager->getTextureDelegate(texture);
/* /!\ VTKTextureWrapMode not yet supported in VTK 7
* See here for some work that needs to be imported back to upstream:
......@@ -379,8 +388,6 @@ VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelega
// Set texture
auto currentTexture = textureDelegate->getVtkTexture();
vtkSmartPointer<vtkActor> actor = vtkActor::SafeDownCast(m_actor);
if (material->getShadingModel() == RenderMaterial::ShadingModel::PBR)
{
switch (texture->getType())
......
......@@ -21,9 +21,7 @@
#pragma once
#include "imstkTextureManager.h"
#include "imstkVTKPolyDataRenderDelegate.h"
#include "imstkVTKTextureDelegate.h"
class vtkCellArray;
class vtkDataArray;
......@@ -62,7 +60,7 @@ public:
///
/// \brief Initialize textures
///
void initializeTextures(TextureManager<VTKTextureDelegate>& textureManager);
void initializeTextures();
// Callbacks for modifications, when an element changes the user or API must post the modified event
// to inform that this happened, if the actual buffer on the geometry is swapped then geometry
......@@ -82,7 +80,7 @@ protected:
///
/// \brief Callback for when RenderMaterial textures are modified
///
///
void texturesModified(Event* e);
protected:
......
......@@ -26,6 +26,7 @@
#include "imstkLogger.h"
#include "imstkScene.h"
#include "imstkSceneObject.h"
#include "imstkTextureManager.h"
#include "imstkVisualModel.h"
#include "imstkVTKSurfaceMeshRenderDelegate.h"
......@@ -51,7 +52,7 @@
namespace imstk
{
VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
m_scene(scene)
m_scene(scene), m_textureManager(std::make_shared<TextureManager<VTKTextureDelegate>>())
{
// create m_vtkRenderer depending on enableVR
if (!enableVR)
......@@ -65,6 +66,7 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
vtkOpenVRRenderer::SafeDownCast(m_vtkRenderer)->SetLightFollowCamera(false);
}
// Process all the changes initially (add all the delegates)
sceneModifed(nullptr);
this->updateRenderDelegates();
......@@ -458,15 +460,15 @@ VTKRenderer::addVisualModel(std::shared_ptr<SceneObject> sceneObject, std::share
<< sceneObject->getName() << "'.";
return;
}
renderDelegate->setTextureManager(m_textureManager);
m_renderedVisualModels[sceneObject].insert(visualModel);
m_objectVtkActors.push_back(renderDelegate->getVtkActor());
m_vtkRenderer->AddActor(renderDelegate->getVtkActor());
auto smRenderDelegate = std::dynamic_pointer_cast<VTKSurfaceMeshRenderDelegate>(renderDelegate);
if (smRenderDelegate)
if (auto smRenderDelegate = std::dynamic_pointer_cast<VTKSurfaceMeshRenderDelegate>(renderDelegate))
{
smRenderDelegate->initializeTextures(m_textureManager);
smRenderDelegate->initializeTextures();
}
visualModel->setRenderDelegateCreated(this, true);
......
......@@ -203,7 +203,7 @@ protected:
std::vector<std::shared_ptr<VTKRenderDelegate>> m_debugRenderDelegates;
// TextureManager is used to share textures among differing delegates
TextureManager<VTKTextureDelegate> m_textureManager;
std::shared_ptr<TextureManager<VTKTextureDelegate>> m_textureManager;
vtkSmartPointer<vtkChartXY> m_timeTableChart;
vtkSmartPointer<vtkContextActor> m_timeTableChartActor;
......
......@@ -50,15 +50,15 @@ VTKTextureDelegate::VTKTextureDelegate(std::shared_ptr<Texture> texture) : m_vtk
for (int i = 0; i < 6; i++)
{
auto index = tFileName.find(".");
auto tempName = tFileName.substr(0, index);
auto index = tFileName.find(".");
auto tempName = tFileName.substr(0, index);
auto extension = tFileName.substr(index);
auto sideName = tempName + sideNames[i] + extension;
auto sideName = tempName + sideNames[i] + extension;
vtkImageReader2* imgReader = readerFactory->CreateImageReader2(sideName.c_str());
CHECK(imgReader != nullptr) << "VTKTextureDelegate::loadTexture error: could not find reader for "
<< sideName;
<< sideName;
auto imageFlip = vtkSmartPointer<vtkImageFlip>::New();
imageFlip->SetFilteredAxis(1);
......@@ -73,12 +73,12 @@ VTKTextureDelegate::VTKTextureDelegate(std::shared_ptr<Texture> texture) : m_vtk
vtkImageReader2* imgReader = readerFactory->CreateImageReader2(tFileName.c_str());
CHECK(imgReader != nullptr) << "VTKTextureDelegate::loadTexture error: could not find reader for "
<< tFileName;
<< tFileName;
imgReader->SetFileName(tFileName.c_str());
imgReader->Update();
m_vtkTexture->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
m_vtkTexture->RepeatOff();
m_vtkTexture->SetRepeat(m_texture->getRepeating());
m_vtkTexture->SetInputConnection(0, imgReader->GetOutputPort());
if (texture->getType() == Texture::Type::Diffuse)
......@@ -92,7 +92,7 @@ VTKTextureDelegate::VTKTextureDelegate(std::shared_ptr<Texture> texture) : m_vtk
// Load by ImageData
vtkSmartPointer<vtkImageData> vtkImgData = GeometryUtils::coupleVtkImageData(imstkImgData);
m_vtkTexture->SetBlendingMode(vtkTexture::VTK_TEXTURE_BLENDING_MODE_ADD);
m_vtkTexture->RepeatOff();
m_vtkTexture->SetRepeat(m_texture->getRepeating());
m_vtkTexture->SetInputData(vtkImgData);
if (texture->getType() == Texture::Type::Diffuse)
......
......@@ -56,7 +56,7 @@ public:
///
/// \brief Get the imstk texture
///
///
std::shared_ptr<Texture> getTexture() const { return m_texture; }
///
......@@ -71,7 +71,7 @@ protected:
protected:
vtkSmartPointer<vtkTexture> m_vtkTexture; ///< VTK texture
std::shared_ptr<Texture> m_texture; ///< iMSTK texture
std::string m_textureName; ///< VTK texture unique name
std::shared_ptr<Texture> m_texture; ///< iMSTK texture
std::string m_textureName; ///< VTK texture unique name
};
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment