//============================================================================
//
// This file is part of the ShapePFCN project.
//
// Copyright (c) 2016-2017 - Evangelos Kalogerakis, Melinos Averkiou, Siddhartha Chaudhuri, Subhransu Maji
//
// ShapePFCN is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// ShapePFCN is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with ShapePFCN. If not, see .
//
//============================================================================
#ifndef __Thea_RenderShape_ShapeRenderer__
#define __Thea_RenderShape_ShapeRenderer__
#include "Common.hpp"
#include "Algorithms/MeshSampler.hpp"
#include "Algorithms/MeshTriangles.hpp"
#include "Algorithms/RayIntersectionTester.hpp" // SDF/UP change
#include "Graphics/Camera.hpp"
#include "Graphics/DisplayMesh.hpp"
#include "Graphics/MeshCodec.hpp"
#include "Graphics/MeshGroup.hpp"
#include "Plugins/GL/GLHeaders.hpp"
#include "Application.hpp"
#include "Ball3.hpp"
#include "ColorRGBA.hpp"
#include "CoordinateFrame3.hpp"
#include "FilePath.hpp"
#include "FileSystem.hpp"
#include "Math.hpp"
#include "Matrix4.hpp"
#include "Plugin.hpp"
#include "UnorderedMap.hpp"
#include "Vector3.hpp"
#include
#include
#include
#include
#include // SDF/UP change
#include "MeshProcessor.hpp"
using namespace std;
using namespace Thea;
using namespace Algorithms;
using namespace Graphics;
ColorRGBA8 indexToColor(uint32 index, bool is_point, bool use_same_index_for_all_channels = false);
ColorRGBA getPaletteColor(long n);
enum ColorMode
{
COLOR_SINGLE_RGB = 0x0000,
COLOR_SINGLE_GRAY = 0x0001,
COLOR_BY_FACE_IDS = 0x0002,
COLOR_BY_FACE_POINT_IDS = 0x0004,
COLOR_BY_FACE_LABELS = 0x0008,
COLOR_BY_FACE_LABELS_WITH_PALETTE = 0x00010,
COLOR_BY_AUX = 0x00020, // SDF/UP change
};
struct FaceColorizer
{
FaceIndexMap const & tri_ids;
FaceIndexMap const & quad_ids;
ColorMode color_mode;
TheaArray const & face_labels;
Vector3 view_vector;
FaceColorizer(FaceIndexMap const & tri_ids_, FaceIndexMap const & quad_ids_, TheaArray const & face_labels_, ColorMode color_mode_,Vector3 view_vector_) :
tri_ids(tri_ids_), quad_ids(quad_ids_), face_labels(face_labels_), color_mode(color_mode_), view_vector(view_vector_)
{
}
bool operator()(DMesh & mesh)
{
mesh.isolateFaces();
mesh.addColors();
DMesh::IndexArray const & tris = mesh.getTriangleIndices();
DMesh::VertexArray const & vertices = mesh.getVertices();
for (array_size_t i = 0; i < tris.size(); i += 3)
{
FaceRef face(&mesh, (long)i / 3);
FaceIndexMap::const_iterator existing = tri_ids.find(face);
if (existing == tri_ids.end())
throw Error(format("Could not find index of triangle %ld in mesh '%s'", (long)i / 3, mesh.getName()));
uint32 id = existing->second;
Vector3 v0 = vertices[tris[i]];
Vector3 v1 = vertices[tris[i+1]];
Vector3 v2 = vertices[tris[i+2]];
Vector3 face_normal = ((v1 - v0).cross(v2 - v0)).unit();
float normal_dot_view = face_normal.dot(-view_vector);
ColorRGBA8 color;
// Paint the face white if its normal dot view vector is smaller than the threshold
if ((color_mode & COLOR_BY_FACE_IDS) | (color_mode & COLOR_BY_FACE_POINT_IDS))
{
if (normal_dot_view < Settings::point_rejection_angle)
{
color.set(255, 255, 255, 255);
}
else
{
color = indexToColor(id, false);
}
}
else if (color_mode & COLOR_BY_FACE_LABELS)
{
if ( (long)id < 0 || (long)id >= face_labels.size() )
{
throw Error(format("Face with ID %d is outside the limits of the face labels array size(%lu)", id, face_labels.size()));
}
color = indexToColor(face_labels[id], false, true);
}
else if (color_mode & COLOR_BY_FACE_LABELS_WITH_PALETTE)
{
if ( (long)id < 0 || (long)id >= face_labels.size() )
{
throw Error(format("Face with ID %d is outside the limits of the face labels array size(%lu)", id, face_labels.size()));
}
color = getPaletteColor(face_labels[id]);
}
else
{
color.set(0, 0, 0, 0); // render black
// throw Error(format("Invalid Color mode"));
}
mesh.setColor((long)tris[i], color);
mesh.setColor((long)tris[i + 1], color);
mesh.setColor((long)tris[i + 2], color);
}
DMesh::IndexArray const & quads = mesh.getQuadIndices();
for (array_size_t i = 0; i < quads.size(); i += 4)
{
FaceRef face(&mesh, (long)i / 4);
FaceIndexMap::const_iterator existing = quad_ids.find(face);
if (existing == quad_ids.end())
throw Error(format("Could not find index of quad %ld in mesh '%s'", (long)i / 4, mesh.getName()));
uint32 id = existing->second;
Vector3 v0 = vertices[quads[i]];
Vector3 v1 = vertices[quads[i + 1]];
Vector3 v2 = vertices[quads[i + 2]];
Vector3 face_normal = ((v1 - v0).cross(v2 - v0)).unit();
float normal_dot_view = face_normal.dot(-view_vector);
ColorRGBA8 color;
// Paint the face white if its normal dot view vector is smaller than the threshold
if (normal_dot_view < Settings::point_rejection_angle)
{
color.set(255, 255, 255, 255);
}
else if ((color_mode & COLOR_BY_FACE_IDS) | (color_mode & COLOR_BY_FACE_POINT_IDS))
{
color = indexToColor(id, false);
}
else if (color_mode & COLOR_BY_FACE_LABELS)
{
if ((long)id < 0 || (long)id >= face_labels.size())
{
throw Error(format("Face with ID %d is outside the limits of the face labels array size(%lu)", id, face_labels.size()));
}
color = indexToColor(face_labels[id], false, true);
}
else if (color_mode & COLOR_BY_FACE_LABELS_WITH_PALETTE)
{
if ((long)id < 0 || (long)id >= face_labels.size())
{
throw Error(format("Face with ID %d is outside the limits of the face labels array size(%lu)", id, face_labels.size()));
}
color = getPaletteColor(face_labels[id]);
}
else
{
color.set(0, 0, 0, 0); // render black
// throw Error(format("Invalid Color mode"));
}
mesh.setColor((long)quads[i], color);
mesh.setColor((long)quads[i + 1], color);
mesh.setColor((long)quads[i + 2], color);
mesh.setColor((long)quads[i + 3], color);
}
return false;
}
};
//Ball3 modelBSphere(Model const & model, Thea::Matrix4 const & transform);
class ShapeRendererImpl
{
private:
static AtomicInt32 has_render_system;
static RenderSystem * render_system;
static Shader * point_shader;
static Shader * mesh_shader;
static Shader * face_index_shader;
string model_path;
Matrix4 transform;
View view;
float zoom;
int out_width, out_height;
bool has_up;
Vector3 view_up;
float point_size;
ColorMode color_mode;
double camera_distance;
//double mesh_radius;
ColorRGBA primary_color;
ColorRGBA background_color;
int antialiasing_level;
bool flat;
Model model;
Image image_with_color;
Image image_with_depth;
Image aux_image; // SDF/UP change
bool loadPlugins();
bool parseArgs(int argc, char ** argv);
bool usage();
bool parseTransform(string const & s, Matrix4 & m);
bool parseViewDiscrete(string const & s, View & view, bool silent = false);
bool parseViewContinuous(string const & s, View & view, bool silent = false);
bool parseViewUp(string const & s, Vector3 & up);
bool parseColor(string const & s, ColorRGBA & c);
void resetArgs();
//bool loadModel(string const & path);
bool renderModel(ColorRGBA const & color, bool draw_points);
void renderSDFImage(Camera const & camera, Matrix4 const & transform, int width, int height, Image & image); // SDF/UP change
void renderCoordImage(Camera const & camera, Matrix4 const & transform, int width, int height, Image & image, bool use_radial_distance, const Thea::Vector3& up_vector); // SDF/UP change
public:
ShapeRendererImpl(const std::string & _mesh_filepath, const Model & _model);
int exec(string const & cmdline);
int exec(int argc, char ** argv);
Image& get_color_image() { return image_with_color; }
Image& get_depth_image() { return image_with_depth; }
Image& get_aux_image() { return aux_image; } // SDF/UP change
}; // class ShapeRendererImpl
class ShapeRenderer
{
public:
ShapeRenderer(const std::string & _mesh_filepath, const Model & _model);
~ShapeRenderer();
int exec(string const & cmdline);
int exec(int argc, char ** argv);
Image& get_color_image() { return impl->get_color_image(); }
Image& get_depth_image() { return impl->get_depth_image(); }
Image& get_aux_image() { return impl->get_aux_image(); } // SDF/UP change
private:
ShapeRendererImpl * impl;
}; // class ShapeRenderer
#endif