Commit f1893282 authored by Nicholas Milef's avatar Nicholas Milef
Browse files

ENH: Added debug color and fixed some small errors with colors

parent c0d1505a
......@@ -31,14 +31,28 @@ SurfaceMesh::initialize(const StdVectorOfVec3d& vertices,
this->clear();
PointSet::initialize(vertices);
setTrianglesVertices(triangles);
this->setTrianglesVertices(triangles);
if (computeDerivedData)
{
computeVertexNormals();
this->computeVertexNormals();
}
}
void
SurfaceMesh::initialize(const StdVectorOfVec3d& vertices,
const std::vector<TriangleArray>& triangles,
const StdVectorOfVec3d& normals,
const bool computeDerivedData)
{
this->initialize(vertices, triangles, computeDerivedData);
this->m_vertexNormals = normals;
this->computeUVSeamVertexGroups();
this->computeVertexNormals();
}
void
SurfaceMesh::clear()
{
......@@ -141,19 +155,39 @@ SurfaceMesh::computeVertexNormals()
this->computeVertexNeighborTriangles();
}
if (m_triangleNormals.empty())
this->computeTrianglesNormals();
StdVectorOfVec3d temp_normals(m_vertexNormals.size());
for (size_t vertexId = 0; vertexId < m_vertexNormals.size(); ++vertexId)
{
this->computeTrianglesNormals();
temp_normals[vertexId] = Vec3d(0, 0, 0);
for (const size_t& triangleId : m_vertexNeighborTriangles.at(vertexId))
{
temp_normals[vertexId] += m_triangleNormals[triangleId];
}
}
// Correct for UV seams
for (size_t vertexId = 0; vertexId < m_vertexNormals.size(); ++vertexId)
{
for (const size_t& triangleId : m_vertexNeighborTriangles.at(vertexId))
NormalGroup group = {m_vertexPositions[vertexId], m_vertexNormals[vertexId]};
m_vertexNormals[vertexId] = temp_normals[vertexId];
if (m_UVSeamVertexGroups.find(group) == m_UVSeamVertexGroups.end())
{
m_vertexNormals.at(vertexId) += m_triangleNormals.at(triangleId);
m_vertexNormals[vertexId].normalize();
continue;
}
m_vertexNormals.at(vertexId).normalize();
auto seamGroup = *m_UVSeamVertexGroups[group].get();
for (auto index : seamGroup)
{
m_vertexNormals[vertexId] += temp_normals[index];
}
m_vertexNormals[vertexId].normalize();
}
}
......@@ -299,6 +333,12 @@ SurfaceMesh::getVertexNormals() const
return m_vertexNormals;
}
StdVectorOfVec3d&
SurfaceMesh::getVertexNormalsNotConst()
{
return m_vertexNormals;
}
void
SurfaceMesh::setVertexTangents(const StdVectorOfVec3d& tangents)
{
......@@ -453,4 +493,24 @@ SurfaceMesh::correctWindingOrder()
}
while (correctedTriangles.size() > 0);
}
void
SurfaceMesh::computeUVSeamVertexGroups()
{
// Reset vertex groups
m_UVSeamVertexGroups.clear();
// Initial pass to bin vertices based on positions
for (size_t i = 0; i < m_vertexPositions.size(); i++)
{
NormalGroup group = {m_vertexPositions[i], m_vertexNormals[i]};
if (m_UVSeamVertexGroups.find(group) == m_UVSeamVertexGroups.end())
{
m_UVSeamVertexGroups.insert(std::pair<NormalGroup, std::shared_ptr<std::vector<size_t>>>(
group, std::make_shared<std::vector<size_t>>()));
}
m_UVSeamVertexGroups[group]->push_back(i);
}
}
} // imstk
......@@ -26,6 +26,8 @@
#include <array>
#include <list>
#include <set>
#include <unordered_set>
#include <memory>
// imstk
#include "imstkPointSet.h"
......@@ -33,6 +35,40 @@
namespace imstk
{
///
/// \brief Helper class for indentifying duplicate points
///
struct NormalGroup
{
Vec3d position;
Vec3d normal;
};
}
// This method is defined to allow for the map to be properly indexed by Texture objects
namespace std
{
template<> struct less<imstk::NormalGroup>
{
bool operator() (const imstk::NormalGroup& group1,
const imstk::NormalGroup& group2) const
{
if (group1.position != group2.position)
{
return (group1.position.x() < group2.position.x());
}
if (group1.normal != group2.normal)
{
return (group1.normal.x() < group2.normal.x());
}
return false;
}
};
}
namespace imstk {
///
/// \class SurfaceMesh
///
/// \brief Surface triangular mesh
......@@ -56,10 +92,19 @@ public:
///
/// \brief Initializes the rest of the data structures given vertex positions and
/// triangle connectivity and texture coordinates
/// triangle connectivity
///
void initialize(const StdVectorOfVec3d& vertices,
const std::vector<TriangleArray>& triangles,
const bool computeDerivedData = false);
///
/// \brief Initializes the rest of the data structures given vertex positions,
/// triangle connectivity, and normals
///
void initialize(const StdVectorOfVec3d& vertices,
const std::vector<TriangleArray>& triangles,
const StdVectorOfVec3d& normals,
const bool computeDerivedData = false);
///
......@@ -161,10 +206,20 @@ public:
///
void correctWindingOrder();
///
/// \brief Finds vertices along vertex seams that share geometric properties
///
void computeUVSeamVertexGroups();
protected:
friend class VTKSurfaceMeshRenderDelegate;
///
/// \brief Get vertex normals
///
StdVectorOfVec3d& getVertexNormalsNotConst();
std::vector<TriangleArray> m_trianglesVertices; ///> Triangle connectivity
std::vector<NeighborsType> m_vertexNeighborTriangles; ///> Neighbor triangles to vertices
......@@ -175,6 +230,8 @@ protected:
StdVectorOfVec3d m_vertexTangents; ///> Tangents of the vertices
StdVectorOfVec3d m_vertexBitangents; ///> Bitangents of the vertices
std::map<NormalGroup, std::shared_ptr<std::vector<size_t>>> m_UVSeamVertexGroups;
std::string m_defaultTCoords = ""; ///> Name of the array used as default material coordinates
};
} // imstk
......
......@@ -52,7 +52,8 @@ AssimpMeshIO::readMeshData(const std::string& filePath)
aiPostProcessSteps::aiProcess_GenSmoothNormals |
aiPostProcessSteps::aiProcess_CalcTangentSpace |
aiPostProcessSteps::aiProcess_JoinIdenticalVertices |
aiPostProcessSteps::aiProcess_Triangulate);
aiPostProcessSteps::aiProcess_Triangulate |
aiPostProcessSteps::aiProcess_ImproveCacheLocality);
// Check if there is actually a mesh or if the file can be read
if (!scene || !scene->HasMeshes())
......@@ -98,8 +99,6 @@ AssimpMeshIO::readMeshData(const std::string& filePath)
triangles[i][2] = indices[2];
}
mesh->initialize(positions, triangles, false);
// Vertex normals, tangents, and bitangents
StdVectorOfVec3d normals(numVertices);
StdVectorOfVec3d tangents(numVertices);
......@@ -132,6 +131,8 @@ AssimpMeshIO::readMeshData(const std::string& filePath)
}
}
mesh->initialize(positions, triangles, normals, false);
mesh->setVertexNormals(normals);
mesh->setVertexTangents(tangents);
mesh->setVertexBitangents(bitangents);
......
......@@ -129,6 +129,19 @@ RenderMaterial::setDiffuseColor(const Color color)
m_modified = true;
}
const Color&
RenderMaterial::getDebugColor() const
{
return m_debugColor;
}
void
RenderMaterial::setDebugColor(const Color color)
{
m_debugColor = color;
m_modified = true;
}
const float&
RenderMaterial::getMetalness() const
{
......
......@@ -81,6 +81,12 @@ public:
const Color& getDiffuseColor() const;
void setDiffuseColor(const Color color);
///
/// \brief Get/Set the color of the wireframe and points
///
const Color& getDebugColor() const;
void setDebugColor(const Color color);
///
/// \brief Get/Set the metalness
///
......@@ -132,6 +138,7 @@ protected:
// Colors
Color m_diffuseColor = Color::White;
Color m_debugColor = Color::Black;
// Classical values
float m_metalness = 0.0; ///< Value for metalness with range: [0.0, 1.0]
......
......@@ -89,9 +89,9 @@ template<> struct less<std::shared_ptr<imstk::Texture>>
bool operator() (const std::shared_ptr<imstk::Texture>& texture1,
const std::shared_ptr<imstk::Texture>& texture2) const
{
if (texture2->getType() != texture2->getType())
if (texture1->getType() != texture2->getType())
{
return (texture2->getType() < texture2->getType());
return (texture1->getType() < texture2->getType());
}
if (texture1->getPath() != texture2->getPath())
......
......@@ -119,23 +119,22 @@ VTKRenderDelegate::make_delegate(std::shared_ptr<Geometry> geom)
void
VTKRenderDelegate::setUpMapper(vtkAlgorithmOutput *source,
const bool rigid,
const bool notSurfaceMesh,
std::shared_ptr<Geometry> geometry)
{
// Add normals
vtkSmartPointer<vtkPolyDataAlgorithm> normalGen;
if (rigid)
if (notSurfaceMesh)
{
vtkSmartPointer<vtkPolyDataAlgorithm> normalGen;
normalGen = vtkSmartPointer<vtkPolyDataNormals>::New();
vtkPolyDataNormals::SafeDownCast(normalGen)->SplittingOff();
normalGen->SetInputConnection(source);
m_mapper->SetInputConnection(normalGen->GetOutputPort());
}
else
{
normalGen = vtkSmartPointer<vtkTriangleMeshPointNormals>::New();
m_mapper->SetInputConnection(source);
}
normalGen->SetInputConnection(source);
m_mapper->SetInputConnection(normalGen->GetOutputPort());
// Disable auto Shift & Scale which is slow for deformable objects
// as it needs to compute a bounding box at every frame
......
......@@ -60,9 +60,12 @@ public:
///
/// \brief Set up normals and mapper
/// \param source input data object
/// \param notSurfaceMesh if the mesh isn't a surface Mesh
/// \param geometry the geometry object
///
void setUpMapper(vtkAlgorithmOutput *source,
const bool rigid,
const bool notSurfaceMesh,
std::shared_ptr<Geometry> geometry);
///
......
......@@ -42,7 +42,8 @@ namespace imstk
{
VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate(std::shared_ptr<SurfaceMesh> surfaceMesh) :
m_geometry(surfaceMesh),
m_mappedVertexArray(vtkSmartPointer<vtkDoubleArray>::New())
m_mappedVertexArray(vtkSmartPointer<vtkDoubleArray>::New()),
m_mappedNormalArray(vtkSmartPointer<vtkDoubleArray>::New())
{
// Map vertices
StdVectorOfVec3d& vertices = m_geometry->getVertexPositionsNotConst();
......@@ -72,6 +73,15 @@ VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate(std::shared_ptr<Surfa
polydata->SetPoints(points);
polydata->SetPolys(cells);
// Map normals
m_geometry->computeVertexNormals();
StdVectorOfVec3d& normals = m_geometry->getVertexNormalsNotConst();
double* normalData = reinterpret_cast<double*>(normals.data());
m_mappedNormalArray->SetNumberOfComponents(3);
m_mappedNormalArray->SetArray(normalData, normals.size()*3, 1);
polydata->GetPointData()->SetNormals(m_mappedNormalArray);
// Create connection source
auto source = vtkSmartPointer<vtkTrivialProducer>::New();
source->SetOutput(polydata);
......@@ -94,7 +104,7 @@ VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate(std::shared_ptr<Surfa
for (auto const tcoord : *tcoords)
{
double tuple[2] = { tcoord[0], tcoord[1] };
float tuple[2] = { tcoord[0], tcoord[1] };
vtkTCoords->InsertNextTuple(tuple);
}
......@@ -129,7 +139,16 @@ VTKSurfaceMeshRenderDelegate::updateDataSource()
{
if (m_geometry->m_dataModified)
{
m_geometry->computeVertexNormals();
StdVectorOfVec3d& normals = m_geometry->getVertexNormalsNotConst();
double* normalData = reinterpret_cast<double*>(normals.data());
m_mappedNormalArray->SetNumberOfComponents(3);
m_mappedNormalArray->SetArray(normalData, normals.size()*3, 1);
this->m_mapper->GetInput()->GetPointData()->SetNormals(m_mappedNormalArray);
m_mappedVertexArray->Modified();
m_mappedNormalArray->Modified();
m_geometry->m_dataModified = false;
}
}
......
......@@ -71,6 +71,7 @@ protected:
std::shared_ptr<SurfaceMesh> m_geometry; ///> Geometry to render
vtkSmartPointer<vtkDoubleArray> m_mappedVertexArray; ///> Mapped array of vertices
vtkSmartPointer<vtkDoubleArray> m_mappedNormalArray; ///> Mapped array of normals
};
}
......
......@@ -20,6 +20,9 @@ uniform vec4 lightDirection[16];
#ifdef SHADED
uniform sampler2D diffuseTexture;
uniform samplerCube cubemapTexture;
uniform vec3 diffuseColorUniform = vec3(1);
#else
uniform vec3 debugColor = vec3(0);
#endif
// Material properties
......@@ -49,6 +52,8 @@ void main()
#ifdef DIFFUSE_TEXTURE
diffuseColor = pow(texture(diffuseTexture, vertex.uv).rgb, vec3(2.2));
#else
diffuseColor = diffuseColorUniform;
#endif
#ifdef CUBEMAP_TEXTURE
reflectionColor = pow(texture(cubemapTexture, reflect(cameraDirection, normal)).rgb, vec3(2.2));
......@@ -93,7 +98,7 @@ void main()
gl_FragData[0] = vec4(pow(finalColor, vec3(1.0 / 2.2)), 1);
#else
gl_FragData[0] = vec4(0, 0, 0, 1);
gl_FragData[0] = vec4(debugColor, 1);
#endif
}
......
......@@ -99,6 +99,7 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
vtkActor * actor)
{
auto textures = this->GetTextures(actor);
auto material = m_geometry->getRenderMaterial();
helper.VAO->Bind();
......@@ -196,8 +197,8 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
helper.AttributeUpdateTime.Modified();
helper.Program->SetUniformf("metalness", m_geometry->getRenderMaterial()->getMetalness());
helper.Program->SetUniformf("roughness", m_geometry->getRenderMaterial()->getRoughness());
helper.Program->SetUniformf("metalness", material->getMetalness());
helper.Program->SetUniformf("roughness", material->getRoughness());
unsigned int textureCount = 0;
unsigned int currentTexture = 0;
......@@ -206,7 +207,11 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
if (this->GetOpenGLMode(actor->GetProperty()->GetRepresentation(), helper.PrimitiveType) == GL_TRIANGLES)
{
auto diffuseTexture = m_geometry->getRenderMaterial()->getTexture(Texture::DIFFUSE);
auto diffuseColorTemp = material->getDiffuseColor();
float diffuseColor[3] = {diffuseColorTemp.r, diffuseColorTemp.g, diffuseColorTemp.b};
helper.Program->SetUniform3f("diffuseColorUniform", diffuseColor);
auto diffuseTexture = material->getTexture(Texture::DIFFUSE);
if (diffuseTexture->getPath() != "" && textureCount < textures.size())
{
auto texture = (vtkOpenGLTexture*)textures[currentTexture];
......@@ -215,7 +220,7 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
currentTexture++;
}
auto cubemapTexture = m_geometry->getRenderMaterial()->getTexture(Texture::CUBEMAP);
auto cubemapTexture = material->getTexture(Texture::CUBEMAP);
if (cubemapTexture->getPath() != "" && textureCount < textures.size())
{
auto texture = (vtkOpenGLTexture*)textures[currentTexture];
......@@ -224,6 +229,14 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
currentTexture++;
}
}
else
{
auto debugColorTemp = material->getDebugColor();
float debugColor[3] = {(float)debugColorTemp.r,
(float)debugColorTemp.g,
(float)debugColorTemp.b};
helper.Program->SetUniform3f("debugColor", debugColor);
}
}
void
......
Supports Markdown
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