Commit 0980b45b authored by Nicholas Milef's avatar Nicholas Milef
Browse files

ENH: improved line mesh class

parent e7eacc0a
###########################################################################
#
# Copyright (c) Kitware, Inc.
#
# 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.
#
###########################################################################
project(Example-LineMesh)
#-----------------------------------------------------------------------------
# Create executable
#-----------------------------------------------------------------------------
add_executable(${PROJECT_NAME} LineMesh.cpp)
#-----------------------------------------------------------------------------
# Add shaders
#-----------------------------------------------------------------------------
include(imstkCopyAndCompileShaders)
CopyAndCompileShaders()
#-----------------------------------------------------------------------------
# Link libraries to executable
#-----------------------------------------------------------------------------
target_link_libraries(${PROJECT_NAME} SimulationManager)
\ No newline at end of file
/*=========================================================================
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 "imstkSimulationManager.h"
#include "imstkMeshIO.h"
#include "imstkPbdObject.h"
#include "imstkPbdSolver.h"
#include "imstkOneToOneMap.h"
#include "imstkAPIUtilities.h"
#include "imstkLineMesh.h"
using namespace imstk;
///
/// \brief This example demonstrates line mesh rendering
///
int main()
{
// SDK and Scene
auto sdk = std::make_shared<SimulationManager>();
auto scene = sdk->createNewScene("LineMeshRenderingTest");
// Construct line mesh
auto lineMesh = std::make_shared<LineMesh>();
auto lineMeshMaterial = std::make_shared<RenderMaterial>();
lineMeshMaterial->setLineWidth(3);
auto lineObject = std::make_shared<VisualObject>("lineMesh");
std::vector<LineMesh::LineArray> lines;
StdVectorOfVec3d points;
std::vector<Color> colors;
size_t resolution = 16;
size_t numVoxels = resolution * resolution * resolution;
points.resize(numVoxels * 8);
colors.resize(numVoxels * 8);
lines.resize(numVoxels * 12);
size_t index = 0;
size_t lineIndex = 0;
for (int z = 0; z < resolution; z++)
{
for (int y = 0; y < resolution; y++)
{
for (int x = 0; x < resolution; x++)
{
Color color = Color((float)x / resolution, (float)y / resolution, (float)z / resolution);
points[index + 0] = Vec3d(x, y, z);
points[index + 1] = Vec3d(x, y, z+1);
points[index + 2] = Vec3d(x, y+1, z);
points[index + 3] = Vec3d(x, y+1, z+1);
points[index + 4] = Vec3d(x+1, y, z);
points[index + 5] = Vec3d(x+1, y, z+1);
points[index + 6] = Vec3d(x+1, y+1, z);
points[index + 7] = Vec3d(x+1, y+1, z+1);
colors[index + 0] = color;
colors[index + 1] = color;
colors[index + 2] = color;
colors[index + 3] = color;
colors[index + 4] = color;
colors[index + 5] = color;
colors[index + 6] = color;
colors[index + 7] = color;
lines[lineIndex + 0][0] = index + 0;
lines[lineIndex + 0][1] = index + 1;
lines[lineIndex + 1][0] = index + 2;
lines[lineIndex + 1][1] = index + 3;
lines[lineIndex + 2][0] = index + 4;
lines[lineIndex + 2][1] = index + 5;
lines[lineIndex + 3][0] = index + 6;
lines[lineIndex + 3][1] = index + 7;
lines[lineIndex + 4][0] = index + 0;
lines[lineIndex + 4][1] = index + 2;
lines[lineIndex + 5][0] = index + 1;
lines[lineIndex + 5][1] = index + 3;
lines[lineIndex + 6][0] = index + 4;
lines[lineIndex + 6][1] = index + 6;
lines[lineIndex + 7][0] = index + 5;
lines[lineIndex + 7][1] = index + 7;
lines[lineIndex + 8][0] = index + 0;
lines[lineIndex + 8][1] = index + 4;
lines[lineIndex + 9][0] = index + 1;
lines[lineIndex + 9][1] = index + 5;
lines[lineIndex + 10][0] = index + 2;
lines[lineIndex + 10][1] = index + 6;
lines[lineIndex + 11][0] = index + 3;
lines[lineIndex + 11][1] = index + 7;
index += 8;
lineIndex += 12;
}
}
}
lineMesh->initialize(points, lines);
lineMesh->setVertexColors(colors);
lineMesh->setRenderMaterial(lineMeshMaterial);
auto camera = scene->getCamera();
camera->setPosition(resolution / 2.0, resolution / 2.0, resolution * 4.0);
camera->setFocalPoint(resolution / 2.0, resolution / 2.0, resolution / 2.0);
lineObject->setVisualGeometry(lineMesh);
scene->addSceneObject(lineObject);
// Start simulation
sdk->setActiveScene(scene);
sdk->startSimulation();
}
......@@ -91,7 +91,7 @@ int main()
auto material = std::make_shared<RenderMaterial>();
material->setBackFaceCulling(false);
material->setDiffuseColor(Color::LightGray);
material->setColor(Color::LightGray);
material->setDisplayMode(RenderMaterial::DisplayMode::WIREFRAME_SURFACE);
surfMesh->setRenderMaterial(material);
......
......@@ -51,7 +51,7 @@ int main()
fluidMesh->initialize(tetMesh->getInitialVertexPositions());
auto material1 = std::make_shared<RenderMaterial>();
material1->setDiffuseColor(Color::Blue);
material1->setColor(Color::Blue);
material1->setSphereGlyphSize(.15);
fluidMesh->setRenderMaterial(material1);
......
......@@ -85,7 +85,7 @@ int main()
// Plane
auto planeObj = apiutils::createVisualAnalyticalSceneObject(Geometry::Type::Plane, scene, "VisualPlane", 10);
auto planeMaterial = std::make_shared<RenderMaterial>();
planeMaterial->setDiffuseColor(Color::DarkGray);
planeMaterial->setColor(Color::DarkGray);
planeObj->getVisualGeometry()->setRenderMaterial(planeMaterial);
// Run
......
......@@ -46,7 +46,7 @@ int main()
// set configure Obj1 rendering
auto matObj1 = std::make_shared<RenderMaterial>();
matObj1->setBackFaceCulling(false);
matObj1->setDiffuseColor(Color::Green);
matObj1->setColor(Color::Green);
matObj1->setDisplayMode(RenderMaterial::DisplayMode::WIREFRAME_SURFACE);
mesh1->setRenderMaterial(matObj1);
......@@ -59,7 +59,7 @@ int main()
// set configure Obj2 rendering
auto matObj2 = std::make_shared<RenderMaterial>();
matObj2->setBackFaceCulling(false);
matObj2->setDiffuseColor(Color::Green);
matObj2->setColor(Color::Green);
matObj2->setDisplayMode(RenderMaterial::DisplayMode::WIREFRAME_SURFACE);
mesh2->setRenderMaterial(matObj2);
......
......@@ -107,7 +107,7 @@ PbdInteractionPair::doNarrowPhaseCollision()
for (int k = 0; k < nL1; ++k)
{
auto nodes = mesh1->getLine(k);
auto nodes = mesh1->getLinesVertices()[k];
unsigned int i1 = nodes[0];
unsigned int i2 = nodes[1];
......
......@@ -25,6 +25,17 @@
namespace imstk
{
void
LineMesh::initialize(const StdVectorOfVec3d& vertices,
const std::vector<LineArray>& lines)
{
this->clear();
PointSet::initialize(vertices);
this->setLinesVertices(lines);
}
void
LineMesh::clear()
{
......@@ -43,9 +54,37 @@ LineMesh::getVolume() const
}
void
LineMesh::setConnectivity(const std::vector<std::vector<int>>& lines)
LineMesh::setVertexColors(const std::vector<Color>& colors)
{
m_lines = lines;
if (colors.size() <= m_maxNumVertices)
{
m_vertexColors = colors;
}
else
{
LOG(WARNING) << "Vertex colors not set, exceeded maximum number of vertices";
}
}
void
LineMesh::setLinesVertices(const std::vector<LineArray>& lines)
{
if (m_originalNumLines == 0)
{
m_originalNumLines = lines.size();
m_maxNumLines = (size_t)(m_originalNumLines * m_loadFactor);
m_lines.reserve(m_maxNumLines);
}
if (lines.size() <= m_maxNumLines)
{
m_topologyChanged = true;
m_lines = lines;
}
else
{
LOG(WARNING) << "Lines not set, exceeded maximum number of lines";
}
}
size_t
......@@ -54,15 +93,15 @@ LineMesh::getNumLines()
return m_lines.size();
}
std::vector<std::vector<int>>
LineMesh::getLines() const
std::vector<LineMesh::LineArray>
LineMesh::getLinesVertices() const
{
return m_lines;
}
std::vector<int>
LineMesh::getLine(int index) const
std::vector<Color>
LineMesh::getVertexColors() const
{
return m_lines[index];
return m_vertexColors;
}
} // imstk
......@@ -23,6 +23,7 @@
#define imstkLineMesh_h
#include <memory>
#include <array>
#include "imstkPointSet.h"
......@@ -38,6 +39,8 @@ class LineMesh : public PointSet
{
public:
using LineArray = std::array<size_t, 2>;
///
/// \brief Constructor
///
......@@ -48,6 +51,13 @@ public:
///
~LineMesh() = default;
///
/// \brief Initializes the rest of the data structures given vertex positions and
/// line connectivity
///
void initialize(const StdVectorOfVec3d& vertices,
const std::vector<LineArray>& lines);
///
/// \brief
///
......@@ -66,7 +76,12 @@ public:
///
/// \brief
///
void setConnectivity(const std::vector<std::vector<int>>& lines);
void setVertexColors(const std::vector<Color>& colors);
///
/// \brief
///
void setLinesVertices(const std::vector<LineArray>& lines);
///
/// \brief
......@@ -76,18 +91,22 @@ public:
///
/// \brief
///
std::vector<std::vector<int>> getLines() const;
std::vector<LineArray> getLinesVertices() const;
///
/// \brief
///
std::vector<int> getLine(int index) const;
std::vector<Color> getVertexColors() const;
private:
friend class VTKLineMeshRenderDelegate;
std::vector<std::vector<int>> m_lines; ///> line connectivity
size_t m_originalNumLines = 0;
size_t m_maxNumLines = 0;
std::vector<LineArray> m_lines; ///> line connectivity
std::vector<Color> m_vertexColors;
};
} // imstk
......
......@@ -173,6 +173,8 @@ public:
protected:
friend class VTKRenderer;
friend class VTKRenderDelegate;
friend class VulkanLineMeshRenderDelegate;
friend class VulkanRenderDelegate;
friend class VulkanSurfaceMeshRenderDelegate;
friend class VulkanRenderer;
......
......@@ -135,15 +135,15 @@ RenderMaterial::backfaceCullingOff()
}
const Color&
RenderMaterial::getDiffuseColor() const
RenderMaterial::getColor() const
{
return m_diffuseColor;
return m_color;
}
void
RenderMaterial::setDiffuseColor(const Color color)
RenderMaterial::setColor(const Color color)
{
m_diffuseColor = color;
m_color = color;
m_modified = true;
}
......@@ -290,4 +290,10 @@ RenderMaterial::isDecal()
{
return m_isDecal;
}
bool
RenderMaterial::isLineMesh()
{
return m_isLineMesh;
}
}
......@@ -84,8 +84,8 @@ public:
///
/// \brief Get/Set the diffuse color
///
const Color& getDiffuseColor() const;
void setDiffuseColor(const Color color);
const Color& getColor() const;
void setColor(const Color color);
///
/// \brief Get/Set the color of the wireframe and points
......@@ -153,10 +153,13 @@ public:
///
bool isDecal();
bool isLineMesh();
protected:
friend class VTKRenderDelegate;
friend class VulkanRenderDelegate;
friend class VulkanDecalRenderDelegate;
friend class VulkanLineMeshRenderDelegate;
// State
DisplayMode m_displayMode = DisplayMode::SURFACE;
......@@ -165,12 +168,13 @@ protected:
float m_pointSize = 1.0;
bool m_backfaceCulling = true; ///< For performance, uncommon for this to be false
bool m_isDecal = false;
bool m_isLineMesh = false;
// Sphere size used for glyph in rendering (valid only for point set)
double m_sphereGlyphSize = 0.05;
// Colors
Color m_diffuseColor = Color::White;
Color m_color = Color::White;
Color m_debugColor = Color::Black;
// Classical values
......
......@@ -39,6 +39,7 @@ set(VULKAN_H_FILES
VulkanRenderer/RenderDelegate/imstkVulkanCapsuleRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanCubeRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanDecalRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanPlaneRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.h
VulkanRenderer/RenderDelegate/imstkVulkanSphereRenderDelegate.h
......@@ -61,6 +62,7 @@ set(VULKAN_CPP_FILES
VulkanRenderer/RenderDelegate/imstkVulkanCapsuleRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanCubeRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanDecalRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanLineMeshRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanPlaneRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanRenderDelegate.cpp
VulkanRenderer/RenderDelegate/imstkVulkanSphereRenderDelegate.cpp
......
......@@ -27,6 +27,9 @@
#include <vtkPolyDataMapper.h>
#include <vtkPoints.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkLine.h>
#include <vtkTrivialProducer.h>
namespace imstk
{
......@@ -45,16 +48,50 @@ VTKLineMeshRenderDelegate::VTKLineMeshRenderDelegate(std::shared_ptr<LineMesh> l
points->SetNumberOfPoints(m_geometry->getNumVertices());
points->SetData(m_mappedVertexArray);
// Create index
auto lineIndices = vtkSmartPointer<vtkCellArray>::New();
for (auto line : m_geometry->getLinesVertices())
{
auto l = vtkSmartPointer<vtkLine>::New();
l->GetPointIds()->SetId(0, line[0]);
l->GetPointIds()->SetId(1, line[1]);
lineIndices->InsertNextCell(l);
}
// Create line
auto lines = vtkSmartPointer<vtkLineSource>::New();
auto lines = vtkSmartPointer<vtkPolyData>::New();
lines->SetPoints(points);
m_geometry->m_dataModified = false;
lines->SetLines(lineIndices);
// Setup Mapper & Actor
this->setUpMapper(lines->GetOutputPort(), true, m_geometry);
// Add colors
if (m_geometry->getVertexColors().size() == m_geometry->getNumVertices())
{
auto colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetNumberOfComponents(3);
colors->SetName("Colors");
for (auto color : m_geometry->getVertexColors())
{
unsigned char c[3] = { (unsigned char)(color.r * 255),
(unsigned char)(color.g * 255),
(unsigned char)(color.b * 255) };
colors->InsertNextTypedTuple(c);
}
lines->GetPointData()->SetScalars(colors);
}
// Create connection source
auto source = vtkSmartPointer<vtkTrivialProducer>::New();
source->SetOutput(lines);
m_geometry->m_dataModified = false;
// Update Transform, Render Properties
this->update();
// Setup Mapper & Actor
this->setUpMapper(source->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -193,7 +193,7 @@ VTKRenderDelegate::updateActorProperties()
auto actorProperty = m_actor->GetProperty();
// Colors & Light
auto diffuseColor = material->m_diffuseColor;
auto diffuseColor = material->m_color;
actorProperty->SetDiffuseColor(diffuseColor.r, diffuseColor.g, diffuseColor.b);
// Material state is now up to date
......
......@@ -208,7 +208,7 @@ VTKCustomPolyDataMapper::SetMapperShaderParameters(
if (this->GetOpenGLMode(actor->GetProperty()->GetRepresentation(), helper.PrimitiveType) == GL_TRIANGLES)
{
auto diffuseColorTemp = material->getDiffuseColor();
auto diffuseColorTemp = material->getColor();
float diffuseColor[3] = {(float)diffuseColorTemp.r,
(float)diffuseColorTemp.g,
(float)diffuseColorTemp.b};
......
......@@ -97,7 +97,7 @@ VulkanCapsuleRenderDelegate::VulkanCapsuleRenderDelegate(std::shared_ptr<Capsule
}
void
VulkanCapsuleRenderDelegate::update(uint32_t frameIndex)
VulkanCapsuleRenderDelegate::update(const uint32_t frameIndex)
{
this->updateUniforms(frameIndex);
}
......
......@@ -49,7 +49,7 @@ public:
///
/// \brief Update render geometry
///
void update(uint32_t frameIndex) override;
void update(const uint32_t frameIndex) override;
///
/// \brief Get source geometry
......
......@@ -97,7 +97,7 @@ VulkanCubeRenderDelegate::VulkanCubeRenderDelegate(std::shared_ptr<Cube> cube, V
}
void
VulkanCubeRenderDelegate::update(uint32_t frameIndex)
VulkanCubeRenderDelegate::update(const uint32_t frameIndex)
{
this->updateUniforms(frameIndex);
}
......
......@@ -49,7 +49,7 @@ public:
///
/// \brief Update render geometry
///
void update(uint32_t frameIndex) override;
void update(const uint32_t frameIndex) override;
///
/// \brief Get source geometry
......