Cleaning of names and reordering of Color functions
This commit is contained in:
parent
d81d14189c
commit
1918c53a09
|
@ -23,40 +23,43 @@
|
||||||
|
|
||||||
#ifndef __VCG_TRI_UPDATE_COLOR
|
#ifndef __VCG_TRI_UPDATE_COLOR
|
||||||
#define __VCG_TRI_UPDATE_COLOR
|
#define __VCG_TRI_UPDATE_COLOR
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <vcg/space/color4.h>
|
#include <vcg/space/color4.h>
|
||||||
#include <vcg/math/histogram.h>
|
#include <vcg/math/histogram.h>
|
||||||
#include <vcg/complex/algorithms/stat.h>
|
|
||||||
#include <vcg/math/perlin_noise.h>
|
#include <vcg/math/perlin_noise.h>
|
||||||
#include <vcg/math/random_generator.h>
|
#include <vcg/math/random_generator.h>
|
||||||
#include <vcg/complex/algorithms/clean.h>
|
#include <vcg/complex/algorithms/clean.h>
|
||||||
|
#include <vcg/complex/algorithms/stat.h>
|
||||||
|
|
||||||
namespace vcg {
|
namespace vcg {
|
||||||
namespace tri {
|
namespace tri {
|
||||||
|
|
||||||
/// \ingroup trimesh
|
/*!
|
||||||
|
\ingroup trimesh
|
||||||
|
|
||||||
/// \headerfile color.h vcg/complex/algorithms/update/color.h
|
\headerfile color.h vcg/complex/algorithms/update/color.h
|
||||||
|
|
||||||
/// \brief Generation of per-vertex and per-face colors according to various strategy.
|
\brief Generation and processing of per-vertex and per-face colors according to various strategy.
|
||||||
/**
|
|
||||||
This class is used to compute per face or per vertex color with respect to for example Border (UpdateColor::VertexBorderFlag), Selection (UpdateColor::FaceSelected), Quality .
|
This class is used to compute per face or per vertex color with respect to a number of algorithms.
|
||||||
|
There is a wide range of algorithms for processing vertex color in a \i photoshop-like mode (changing for example contrast, white balance, gamma)
|
||||||
|
Basic Tools for mapping quality into a color according to standard color ramps are here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <class UpdateMeshType>
|
template <class MeshType>
|
||||||
class UpdateColor
|
class UpdateColor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef UpdateMeshType MeshType;
|
typedef typename MeshType::VertexType VertexType;
|
||||||
typedef typename UpdateMeshType::VertexType VertexType;
|
typedef typename MeshType::VertexPointer VertexPointer;
|
||||||
typedef typename UpdateMeshType::VertexPointer VertexPointer;
|
typedef typename MeshType::VertexIterator VertexIterator;
|
||||||
typedef typename UpdateMeshType::VertexIterator VertexIterator;
|
typedef typename MeshType::FaceType FaceType;
|
||||||
typedef typename UpdateMeshType::FaceType FaceType;
|
typedef typename MeshType::FacePointer FacePointer;
|
||||||
typedef typename UpdateMeshType::FacePointer FacePointer;
|
typedef typename MeshType::FaceIterator FaceIterator;
|
||||||
typedef typename UpdateMeshType::FaceIterator FaceIterator;
|
typedef typename MeshType::ScalarType ScalarType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ColorAvgInfo
|
class ColorAvgInfo
|
||||||
{
|
{
|
||||||
|
@ -68,11 +71,48 @@ typedef typename UpdateMeshType::FaceIterator FaceIterator;
|
||||||
int cnt;
|
int cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void VertexFromFace( UpdateMeshType &m)
|
/*! \brief This function colores all (or the selected) the vertices of a mesh.
|
||||||
|
*/
|
||||||
|
static int PerVertexConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
||||||
|
{
|
||||||
|
int cnt=0;
|
||||||
|
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
|
if(!(*vi).IsD()){
|
||||||
|
if(!selected || (*vi).IsS())
|
||||||
|
{
|
||||||
|
(*vi).C() = vs;
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores all (or the selected) faces of a mesh.
|
||||||
|
*/
|
||||||
|
static int PerFaceConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
|
||||||
|
{
|
||||||
|
int cnt=0;
|
||||||
|
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
|
||||||
|
if(!(*fi).IsD()){
|
||||||
|
if(!selected || (*fi).IsS())
|
||||||
|
{
|
||||||
|
(*fi).C() = vs;
|
||||||
|
++cnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Transfer face color onto vertex color
|
||||||
|
|
||||||
|
Plain average of the color of the faces incident on a given vertex.
|
||||||
|
No adjacency required.
|
||||||
|
*/
|
||||||
|
static void PerVertexFromFace( MeshType &m)
|
||||||
{
|
{
|
||||||
ColorAvgInfo csi;
|
ColorAvgInfo csi;
|
||||||
csi.r=0; csi.g=0; csi.b=0; csi.cnt=0;
|
csi.r=0; csi.g=0; csi.b=0; csi.cnt=0;
|
||||||
SimpleTempData<typename UpdateMeshType::VertContainer, ColorAvgInfo> TD(m.vert,csi);
|
SimpleTempData<typename MeshType::VertContainer, ColorAvgInfo> TD(m.vert,csi);
|
||||||
|
|
||||||
FaceIterator fi;
|
FaceIterator fi;
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
||||||
|
@ -97,7 +137,10 @@ typedef typename UpdateMeshType::FaceIterator FaceIterator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FaceFromVertex( UpdateMeshType &m)
|
/*! \brief Transfer vertex color onto face color
|
||||||
|
Plain average of the color of the vertexes on a given face.
|
||||||
|
*/
|
||||||
|
static void PerFaceFromVertex( MeshType &m)
|
||||||
{
|
{
|
||||||
FaceIterator fi;
|
FaceIterator fi;
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
||||||
|
@ -109,29 +152,99 @@ typedef typename UpdateMeshType::FaceIterator FaceIterator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores all the faces of a mesh with a hue color shade dependent on the quality.
|
||||||
|
|
||||||
|
If no range of quality is passed it is automatically computed.
|
||||||
|
*/
|
||||||
|
static void PerVertexQualityRamp(MeshType &m, float minq=0, float maxq=0)
|
||||||
|
{
|
||||||
|
if(!HasPerVertexQuality(m)) throw MissingComponentException("PerVertexQuality");
|
||||||
|
|
||||||
/// \brief Color the vertexes of the mesh that are on the border
|
if(minq==maxq)
|
||||||
|
{
|
||||||
|
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||||
|
minq=minmax.first;
|
||||||
|
maxq=minmax.second;
|
||||||
|
}
|
||||||
|
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
|
if(!(*vi).IsD())
|
||||||
|
(*vi).C().SetColorRamp(minq,maxq,(*vi).Q());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/*! \brief This function colores all the faces of a mesh with a hue color shade dependent on the quality.
|
||||||
It uses the information in the Vertex flags, and not any topology.
|
|
||||||
So it just require that you have correctly computed the flags;
|
|
||||||
|
|
||||||
- vcg::tri::UpdateTopology<Mesh>::FaceFace(m.cm);
|
If no range of quality is passed it is automatically computed.
|
||||||
- vcg::tri::UpdateFlags<Mesh>::FaceBorderFromFF(m.cm);
|
*/
|
||||||
- vcg::tri::UpdateFlags<Mesh>::VertexBorderFromFace (m.cm);
|
static void PerFaceQualityRamp(MeshType &m, float minq=0, float maxq=0, bool selected=false)
|
||||||
- vcg::tri::UpdateColor<Mesh>::VertexBorderFlag(m.cm);
|
{
|
||||||
|
if(!HasPerFaceQuality(m)) throw MissingComponentException("PerFaceQuality");
|
||||||
|
|
||||||
|
if(minq==maxq)
|
||||||
|
{
|
||||||
|
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
|
minq=minmax.first;
|
||||||
|
maxq=minmax.second;
|
||||||
|
}
|
||||||
|
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
||||||
|
if(!selected || (*fi).IsS())
|
||||||
|
(*fi).C().SetColorRamp(minq,maxq,(*fi).Q());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores all the vertices of a mesh with a gray shade dependent on the quality.
|
||||||
|
|
||||||
|
If no range of quality is passed it is automatically computed.
|
||||||
|
*/
|
||||||
|
static void PerVertexQualityGray(MeshType &m, float minq, float maxq)
|
||||||
|
{
|
||||||
|
if(!HasPerVertexQuality(m)) throw MissingComponentException("PerVertexQuality");
|
||||||
|
if(minq==maxq)
|
||||||
|
{
|
||||||
|
std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
|
||||||
|
minq=minmax.first;
|
||||||
|
maxq=minmax.second;
|
||||||
|
}
|
||||||
|
for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
|
if(!(*vi).IsD())
|
||||||
|
(*vi).C().SetGrayShade( ((*vi).Q()-minq)/(maxq-minq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores all the faces of a mesh with a gray shade dependent on the quality.
|
||||||
|
|
||||||
|
If no range of quality is passed it is automatically computed.
|
||||||
|
*/
|
||||||
|
static void PerFaceQualityGray(MeshType &m, float minq=0, float maxq=0)
|
||||||
|
{
|
||||||
|
if(!HasPerFaceQuality(m)) throw MissingComponentException("PerFaceQuality");
|
||||||
|
|
||||||
|
if(minq==maxq)
|
||||||
|
{
|
||||||
|
std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
|
||||||
|
minq=minmax.first;
|
||||||
|
maxq=minmax.second;
|
||||||
|
}
|
||||||
|
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
||||||
|
(*fi).C().SetGrayShade( ((*fi).Q()-minq)/(maxq-minq));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief Color the vertexes of the mesh that are on the border
|
||||||
|
|
||||||
|
It uses the information in the Vertex flags, and not necessarily any topology.
|
||||||
|
So it just require that you have correctly computed the flags; one way could be the following one:
|
||||||
|
\code
|
||||||
|
vcg::tri::UpdateTopology<Mesh>::FaceFace(m.cm);
|
||||||
|
vcg::tri::UpdateFlags<Mesh>::FaceBorderFromFF(m.cm);
|
||||||
|
vcg::tri::UpdateFlags<Mesh>::VertexBorderFromFace (m.cm);
|
||||||
|
vcg::tri::UpdateColor<Mesh>::PerVertexBorderFlag(m.cm);
|
||||||
|
\endcode
|
||||||
*/
|
*/
|
||||||
static void VertexBorderFlag( UpdateMeshType &m, Color4b BorderColor=Color4b::Blue, Color4b InternalColor=Color4b::White, Color4b MixColor=Color4b::Cyan)
|
static void PerVertexBorderFlag( MeshType &m, Color4b BorderColor=Color4b::Blue, Color4b InternalColor=Color4b::White, Color4b MixColor=Color4b::Cyan)
|
||||||
{
|
{
|
||||||
Color4b BaseColor = Color4b::Green;
|
Color4b BaseColor = Color4b::Green;
|
||||||
|
|
||||||
VertexConstant(m,BaseColor);
|
VertexConstant(m,BaseColor);
|
||||||
|
for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
|
||||||
for(int j=0;j<3;++j)
|
for(int j=0;j<3;++j)
|
||||||
|
{
|
||||||
if((*fi).IsB(j)){
|
if((*fi).IsB(j)){
|
||||||
if( (*fi).V(j)->C() == BaseColor) (*fi).V(j)->C() = BorderColor;
|
if( (*fi).V(j)->C() == BaseColor) (*fi).V(j)->C() = BorderColor;
|
||||||
if( (*fi).V(j)->C() == InternalColor) (*fi).V(j)->C() = MixColor;
|
if( (*fi).V(j)->C() == InternalColor) (*fi).V(j)->C() = MixColor;
|
||||||
|
@ -144,16 +257,20 @@ static void VertexBorderFlag( UpdateMeshType &m, Color4b BorderColor=Color4b::Bl
|
||||||
if( (*fi).V1(j)->C() == BaseColor) (*fi).V1(j)->C() = InternalColor;
|
if( (*fi).V1(j)->C() == BaseColor) (*fi).V1(j)->C() = InternalColor;
|
||||||
if( (*fi).V1(j)->C() == BorderColor) (*fi).V1(j)->C() = MixColor;
|
if( (*fi).V1(j)->C() == BorderColor) (*fi).V1(j)->C() = MixColor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief This function colores the faces of connected components of a mesh randomly.
|
||||||
|
|
||||||
/// This function colores the face of a mesh randomly.
|
It require FaceFace Adjacency becouse it relies on the output of the ConnecteComponents();
|
||||||
/// The faux bit is used to color polygonal faces uniformly
|
*/
|
||||||
static void FaceRandomConnectedComponent( UpdateMeshType &m)
|
static void PerFaceRandomConnectedComponent( MeshType &m)
|
||||||
{
|
{
|
||||||
std::vector< std::pair<int, typename UpdateMeshType::FacePointer> > CCV;
|
if(!HasFFAdjacency(m)) throw MissingComponentException("FFAdjacency");
|
||||||
int ScatterSize= std::min (100,tri::Clean<UpdateMeshType>::ConnectedComponents(m, CCV)); // number of random color to be used. Never use too many.
|
|
||||||
|
std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
|
||||||
|
int ScatterSize= std::min (100,tri::Clean<MeshType>::ConnectedComponents(m, CCV)); // number of random color to be used. Never use too many.
|
||||||
|
|
||||||
ConnectedIterator<MeshType> ci;
|
ConnectedIterator<MeshType> ci;
|
||||||
for(unsigned int i=0;i<CCV.size();++i)
|
for(unsigned int i=0;i<CCV.size();++i)
|
||||||
|
@ -163,15 +280,17 @@ static void FaceRandomConnectedComponent( UpdateMeshType &m)
|
||||||
for(ci.start(m,CCV[i].second);!ci.completed();++ci)
|
for(ci.start(m,CCV[i].second);!ci.completed();++ci)
|
||||||
(*ci)->C()=BaseColor;
|
(*ci)->C()=BaseColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function colores the face of a mesh randomly.
|
/*! \brief This function colores the face of a mesh randomly.
|
||||||
/// The faux bit is used to color polygonal faces uniformly
|
|
||||||
static void MultiFaceRandom( UpdateMeshType &m)
|
Note: The faux bit is used to color polygonal faces uniformly
|
||||||
{
|
*/
|
||||||
|
static void PerFaceRandom(MeshType &m)
|
||||||
|
{
|
||||||
FaceIterator fi;
|
FaceIterator fi;
|
||||||
Color4b BaseColor = Color4b::Black;
|
Color4b BaseColor = Color4b::Black;
|
||||||
FaceConstant(m,BaseColor);
|
PerFaceConstant(m,BaseColor);
|
||||||
int id_num=0;
|
int id_num=0;
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
||||||
if(!(*fi).IsD())
|
if(!(*fi).IsD())
|
||||||
|
@ -185,191 +304,51 @@ static void MultiFaceRandom( UpdateMeshType &m)
|
||||||
(*fi).FFp(j)->C()= (*fi).C();
|
(*fi).FFp(j)->C()= (*fi).C();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FaceBF( UpdateMeshType &m, Color4b vn=Color4b::White, Color4b vb=Color4b::Blue,
|
/*! \brief Perlin Noise.
|
||||||
Color4b vc=Color4b::Red, Color4b vs=Color4b::LightBlue)
|
\return the number of changed vertexes (the selected ones)
|
||||||
{
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
|
||||||
if(!(*fi).IsD())
|
|
||||||
(*fi).C() = vn;
|
|
||||||
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
Simple Perlin noise. To make things weirder each color band can be offset.
|
||||||
if(!(*fi).IsD())
|
*/
|
||||||
|
static void PerVertexPerlinNoise(MeshType& m, Box3f bbox, Matrix44<ScalarType> tr, float freq, Point3i channelOffsets=Point3i(0,0,0))
|
||||||
{
|
{
|
||||||
if((*fi).IsS())
|
Point3<ScalarType> p;
|
||||||
(*fi).C() = vs;
|
for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for(int j=0;j<3;++j)
|
|
||||||
if(*fi.IsManifold(j)){
|
|
||||||
if((*fi).IsB(j)){
|
|
||||||
(*fi).C() = vb;
|
|
||||||
(*fi).C() = vb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
(*fi).C() = vc;
|
|
||||||
(*fi).C() = vc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int FaceSelected(UpdateMeshType &m, Color4b vs=Color4b::LightBlue)
|
|
||||||
{
|
|
||||||
int cnt=0;
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
|
||||||
if(!(*fi).IsD()){
|
|
||||||
if((*fi).IsS()) { (*fi).C() = vs; ++cnt; }
|
|
||||||
else (*fi).C() = Color4b::White;
|
|
||||||
}
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int VertexSelected(UpdateMeshType &m, Color4b vs=Color4b::LightBlue)
|
|
||||||
{
|
|
||||||
int cnt=0;
|
|
||||||
typename UpdateMeshType::VertexIterator vi;
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
|
||||||
if(!(*vi).IsD()){
|
if(!(*vi).IsD()){
|
||||||
if((*vi).IsS()) {(*vi).C() = vs; ++cnt; }
|
p = bbox.GlobalToLocal(tr * (*vi).P()); //actual vertex position scaled to bbox
|
||||||
else (*vi).C() = Color4b::White;
|
(*vi).C() = Color4b( int(255*math::Perlin::Noise(channelOffsets[0]+p[0]*freq,channelOffsets[0]+p[1]*freq,channelOffsets[0]+p[2]*freq)),
|
||||||
}
|
int(255*math::Perlin::Noise(channelOffsets[1]+p[0]*freq,channelOffsets[1]+p[1]*freq,channelOffsets[1]+p[2]*freq)),
|
||||||
return cnt;
|
int(255*math::Perlin::Noise(channelOffsets[2]+p[0]*freq,channelOffsets[2]+p[1]*freq,channelOffsets[2]+p[2]*freq)),
|
||||||
}
|
255 );
|
||||||
|
|
||||||
static void VertexConstant(UpdateMeshType &m, Color4b c=Color4b::White)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::VertexIterator vi;
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
|
|
||||||
(*vi).C()=c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FaceConstant(UpdateMeshType &m, Color4b c=Color4b::White)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
|
||||||
(*fi).C()=c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VertexBorderManifoldFlag(UpdateMeshType &m, Color4b vn=Color4b::White, Color4b vb=Color4b::Blue, Color4b vc=Color4b::Red)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::VertexIterator vi;
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) if(!(*vi).IsD())
|
|
||||||
(*vi).C()=vn;
|
|
||||||
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
|
||||||
if(!(*fi).IsD())
|
|
||||||
for(int j=0;j<3;++j)
|
|
||||||
if((*fi).IsManifold(j)){
|
|
||||||
if((*fi).IsB(j)){
|
|
||||||
(*fi).V(j)->C()=vb;
|
|
||||||
(*fi).V1(j)->C()=vb;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
/*! \brief Simple Noise adding function.
|
||||||
|
It simply add signed noise to the color of the mesh. The noise has uniform distribution and the amplitude is +/-2^(noisebits-1).
|
||||||
|
*/
|
||||||
|
static void PerVertexAddNoise(MeshType& m, int noiseBits)
|
||||||
{
|
{
|
||||||
(*fi).V(j)->C()=vc;
|
if(noiseBits>8) noiseBits = 8;
|
||||||
(*fi).V1(j)->C()=vc;
|
if(noiseBits<1) return;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FaceQualityGray(UpdateMeshType &m, float minq, float maxq)
|
math::SubtractiveRingRNG randomGen = math::SubtractiveRingRNG(time(NULL));
|
||||||
{
|
for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
|
||||||
(*fi).C().SetGrayShade( ((*fi).Q()-minq)/(maxq-minq));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FaceQualityGray(UpdateMeshType &m)
|
|
||||||
{
|
|
||||||
std::pair<float,float> minmax = Stat<UpdateMeshType>::ComputePerFaceQualityMinMax(m);
|
|
||||||
FaceQualityGray(m,minmax.first,minmax.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FaceQualityRamp(UpdateMeshType &m,bool selected=false)
|
|
||||||
{
|
|
||||||
// step 1: find the range
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
float minq=std::numeric_limits<float>::max(),
|
|
||||||
maxq=-std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
|
||||||
if(!selected || (*fi).IsS())
|
|
||||||
{
|
{
|
||||||
minq=std::min(minq,(float)(*fi).Q());
|
if(!(*vi).IsD()){
|
||||||
maxq=std::max(maxq,(float)(*fi).Q());
|
(*vi).C()[0] = math::Clamp<int>((*vi).C()[0] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
||||||
}
|
(*vi).C()[1] = math::Clamp<int>((*vi).C()[1] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
||||||
|
(*vi).C()[2] = math::Clamp<int>((*vi).C()[2] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
||||||
FaceQualityRamp(m,minq,maxq,selected);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FaceQualityRamp(UpdateMeshType &m, float minq, float maxq,bool selected=false)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::FaceIterator fi;
|
|
||||||
for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
|
|
||||||
if(!selected || (*fi).IsS())
|
|
||||||
(*fi).C().SetColorRamp(minq,maxq,(*fi).Q());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VertexQualityRamp(UpdateMeshType &m, float minq, float maxq)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::VertexIterator vi;
|
|
||||||
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
|
||||||
if(!(*vi).IsD())
|
|
||||||
(*vi).C().SetColorRamp(minq,maxq,(*vi).Q());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VertexQualityRamp(UpdateMeshType &m)
|
|
||||||
{
|
|
||||||
std::pair<float,float> minmax = Stat<UpdateMeshType>::ComputePerVertexQualityMinMax(m);
|
|
||||||
VertexQualityRamp(m,minmax.first,minmax.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VertexQualityGray(UpdateMeshType &m, const float minq, const float maxq)
|
|
||||||
{
|
|
||||||
typename UpdateMeshType::VertexIterator vi;
|
|
||||||
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
|
||||||
if(!(*vi).IsD())
|
|
||||||
(*vi).C().SetGrayShade( ((*vi).Q()-minq)/(maxq-minq));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void VertexQualityGray(UpdateMeshType &m)
|
|
||||||
{
|
|
||||||
std::pair<float,float> minmax = Stat<UpdateMeshType>::ComputePerVertexQualityMinMax( m);
|
|
||||||
VertexQualityGray(m,minmax.first,minmax.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Fill the mesh with the selected color.
|
|
||||||
static int Filling(UpdateMeshType &m, Color4b c, const bool ProcessSelected=false)
|
|
||||||
{
|
|
||||||
int counter=0;
|
|
||||||
VertexIterator vi;
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
|
||||||
{
|
|
||||||
if(!(*vi).IsD()) //if it has not been deleted...
|
|
||||||
{
|
|
||||||
if(!ProcessSelected || (*vi).IsS()) //if this vertex has been selected, do transormation
|
|
||||||
{
|
|
||||||
(*vi).C() = c;
|
|
||||||
++counter;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Reduces the mesh to two colors according to a threshold.
|
|
||||||
static int Thresholding(UpdateMeshType &m, float threshold, Color4b c1 = Color4<unsigned char>::Black, Color4b c2 = Color4<unsigned char>::White, const bool ProcessSelected=false)
|
/*! \brief Reduces vertex color the mesh to two colors according to a threshold.
|
||||||
|
*/
|
||||||
|
static int PerVertexThresholding(MeshType &m, float threshold, Color4b c1 = Color4<unsigned char>::Black, Color4b c2 = Color4<unsigned char>::White, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -390,7 +369,7 @@ static int Thresholding(UpdateMeshType &m, float threshold, Color4b c1 = Color4<
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Computes the lightness value for a specified color. lightness = 0.5*(Max(R,G,B)+Min(R,G,B))
|
// Computes the lightness value for a specified color. lightness = 0.5*(Max(R,G,B)+Min(R,G,B))
|
||||||
static float ComputeLightness(Color4b c)
|
static float ComputeLightness(Color4b c)
|
||||||
{
|
{
|
||||||
float min_rgb = (float)math::Min(c[0],c[1],c[2]);
|
float min_rgb = (float)math::Min(c[0],c[1],c[2]);
|
||||||
|
@ -398,8 +377,9 @@ static float ComputeLightness(Color4b c)
|
||||||
return (max_rgb + min_rgb)/2;
|
return (max_rgb + min_rgb)/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply the brightness filter, with the given amount, to the mesh.
|
/*! \brief Apply the brightness filter, with the given amount, to the mesh.
|
||||||
static int Brighting(UpdateMeshType &m, float amount, const bool ProcessSelected=false)
|
*/
|
||||||
|
static int PerVertexBrightness(MeshType &m, float amount, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -421,8 +401,9 @@ static int Brighting(UpdateMeshType &m, float amount, const bool ProcessSelected
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply Contrast filter to the mesh with the given contrast factor.
|
/*! \brief Apply Contrast filter to the mesh with the given contrast factor.
|
||||||
static int Contrast(UpdateMeshType &m, float factor, const bool ProcessSelected=false)
|
*/
|
||||||
|
static int PerVertexContrast(MeshType &m, float factor, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -452,8 +433,15 @@ static int ValueMul(int value, float factor)
|
||||||
return math::Clamp<int>((int)((value - 128)*factor + 128), 0, 255);
|
return math::Clamp<int>((int)((value - 128)*factor + 128), 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply Brightness and Contrast filter to the mesh, with the given contrast factor and brightness amount.
|
/*! \brief Apply Brightness and Contrast filter to the mesh, with the given contrast factor and brightness amount.
|
||||||
static int BrightnessContrast(UpdateMeshType &m, float brightness, float contrast, const bool ProcessSelected=false)
|
|
||||||
|
Performs contrast and brightness operations on color, i.e NewValue = (OldValue - 128) * contrast + 128 + amount
|
||||||
|
The result is clamped just one time after all computations; this get a more accurate result.
|
||||||
|
|
||||||
|
The formula used here is the one of GIMP.
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int PerVertexBrightnessContrast(MeshType &m, float brightness, float contrast, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -471,9 +459,6 @@ static int BrightnessContrast(UpdateMeshType &m, float brightness, float contras
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Performs contrast and brightness operations on color, i.e NewValue = (OldValue - 128) ◊ contrast + 128 + amount
|
|
||||||
//The result is clamped just one time after all computations; this get a more accurate result.
|
|
||||||
// The formula used here is the one of GIMP.
|
|
||||||
static Color4b ColorBrightnessContrast(Color4b c, float brightness, float contrast)
|
static Color4b ColorBrightnessContrast(Color4b c, float brightness, float contrast)
|
||||||
{
|
{
|
||||||
return Color4b( ValueBrightnessContrast(c[0], brightness, contrast),
|
return Color4b( ValueBrightnessContrast(c[0], brightness, contrast),
|
||||||
|
@ -490,18 +475,21 @@ static int ValueBrightnessContrast(unsigned char ivalue, float brightness, float
|
||||||
return math::Clamp<int>(255.0*value, 0, 255);
|
return math::Clamp<int>(255.0*value, 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Invert the colors of the mesh.
|
/*! \brief Invert the colors of the mesh.
|
||||||
static int Invert(UpdateMeshType &m, const bool ProcessSelected=false)
|
|
||||||
|
\return the number of changed vertexes (the selected ones)
|
||||||
|
*/
|
||||||
|
static int PerVertexInvert(MeshType &m, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi) //scan all the vertex...
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
|
||||||
{
|
{
|
||||||
if(!(*vi).IsD()) //if it has not been deleted...
|
if(!(*vi).IsD()) //if it has not been deleted...
|
||||||
{
|
{
|
||||||
if(!ProcessSelected || (*vi).IsS()) //if this vertex has been selected, do transormation
|
if(!ProcessSelected || (*vi).IsS()) //if this vertex has been selected, do transormation
|
||||||
{
|
{
|
||||||
(*vi).C() = ColorInvert((*vi).C());
|
Color4b &c=(*vi).C();
|
||||||
|
c=Color4b( 255-c[0],255-c[1],255-c[2], 1);
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,18 +497,10 @@ static int Invert(UpdateMeshType &m, const bool ProcessSelected=false)
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Invert the rgb component of the color
|
/*! \brief Apply the gamma correction filter, with the given gamma exponet, to the mesh.
|
||||||
static Color4b ColorInvert(Color4b c)
|
\return the number of changed vertexes (the selected ones)
|
||||||
{
|
*/
|
||||||
return Color4b( ValueInvert(c[0]), ValueInvert(c[1]), ValueInvert(c[2]), 1);
|
static int PerVertexGamma(MeshType &m, float gamma, const bool ProcessSelected=false)
|
||||||
}
|
|
||||||
|
|
||||||
static int ValueInvert(int value)
|
|
||||||
{
|
|
||||||
return 255-value;
|
|
||||||
}
|
|
||||||
//Apply the gamma correction filter, with the given gamma exponet, to the mesh.
|
|
||||||
static int Gamma(UpdateMeshType &m, float gamma, const bool ProcessSelected=false)
|
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
|
|
||||||
|
@ -557,10 +537,15 @@ static float ValuePow(float value, float exponent)
|
||||||
//useful bit masks for RGB channels, used for Levels filter.
|
//useful bit masks for RGB channels, used for Levels filter.
|
||||||
enum rgbChMask {ALL_CHANNELS = 7, RED_CHANNEL = 4, GREEN_CHANNEL = 2, BLUE_CHANNEL = 1, NO_CHANNELS = 0 };
|
enum rgbChMask {ALL_CHANNELS = 7, RED_CHANNEL = 4, GREEN_CHANNEL = 2, BLUE_CHANNEL = 1, NO_CHANNELS = 0 };
|
||||||
|
|
||||||
//Adjusts color levels of the mesh. Filter can be applied to all RGB channels or to each channel separately.
|
/*! \brief Adjusts color levels of the mesh
|
||||||
//in_min, gamma and in_max are respectively the black point, the gray point and the white point.
|
|
||||||
//out_min and out_max are the output level for black and white respectively.
|
\return the number of changed vertexes (the selected ones)
|
||||||
static int Levels(UpdateMeshType &m, float gamma, float in_min, float in_max, float out_min, float out_max, unsigned char rgbMask, const bool ProcessSelected=false)
|
|
||||||
|
Adjusts color levels of the mesh. Filter can be applied to all RGB channels or to each channel separately.
|
||||||
|
in_min, gamma and in_max are respectively the black point, the gray point and the white point.
|
||||||
|
out_min and out_max are the output level for black and white respectively.
|
||||||
|
*/
|
||||||
|
static int PerVertexLevels(MeshType &m, float gamma, float in_min, float in_max, float out_min, float out_max, unsigned char rgbMask, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -602,12 +587,16 @@ static int ValueLevels(int value, float gamma, float in_min, float in_max, float
|
||||||
return math::Clamp<int>((int)(fvalue * 255), 0, 255);
|
return math::Clamp<int>((int)(fvalue * 255), 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Colors the mesh. Color is blended to the mesh with the given intensity.
|
/*! \brief Colorize the mesh toward a given color.
|
||||||
static int Colourisation(UpdateMeshType &m, Color4b c, float intensity, const bool ProcessSelected=false)
|
\return the number of changed vertexes (the selected ones)
|
||||||
|
|
||||||
|
Colors the mesh. Color is blended to the mesh with the given intensity (0..1 ranged).
|
||||||
|
*/
|
||||||
|
static int PerVertexColourisation(MeshType &m, Color4b c, float intensity, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
{
|
{
|
||||||
if(!(*vi).IsD()) //if it has not been deleted...
|
if(!(*vi).IsD()) //if it has not been deleted...
|
||||||
{
|
{
|
||||||
|
@ -621,10 +610,14 @@ static int Colourisation(UpdateMeshType &m, Color4b c, float intensity, const bo
|
||||||
return counter;
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Perform colourisation operation. For each channel C: newC = origC + intensity * (newC - origC)
|
// Perform colourisation operation.
|
||||||
|
// For each channel C:
|
||||||
|
// newC = origC + intensity * (newC - origC)
|
||||||
static Color4b ColorApplyDiff(Color4b old_color, Color4b new_color, float intensity)
|
static Color4b ColorApplyDiff(Color4b old_color, Color4b new_color, float intensity)
|
||||||
{
|
{
|
||||||
return Color4b( ValueApplyDiff(old_color[0],new_color[0],intensity), ValueApplyDiff(old_color[1],new_color[1],intensity), ValueApplyDiff(old_color[2], new_color[2],intensity), 255);
|
return Color4b( ValueApplyDiff(old_color[0], new_color[0], intensity),
|
||||||
|
ValueApplyDiff(old_color[1], new_color[1], intensity),
|
||||||
|
ValueApplyDiff(old_color[2], new_color[2], intensity), 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ValueApplyDiff(int old_value, int new_value, float intensity)
|
static int ValueApplyDiff(int old_value, int new_value, float intensity)
|
||||||
|
@ -635,8 +628,16 @@ static int ValueApplyDiff(int old_value, int new_value, float intensity)
|
||||||
//An useful ENUM to hold all desaturation methods.
|
//An useful ENUM to hold all desaturation methods.
|
||||||
enum DesaturationMethods {M_LIGHTNESS = 0, M_LUMINOSITY = 1, M_AVERAGE = 2};
|
enum DesaturationMethods {M_LIGHTNESS = 0, M_LUMINOSITY = 1, M_AVERAGE = 2};
|
||||||
|
|
||||||
//Desaturates the mesh according the selected method. Method belongs to DesaturationMethods's ENUM.
|
/*! \brief Desaturates the mesh according the a chosen desaturation method
|
||||||
static int Desaturation(UpdateMeshType &m, int method, const bool ProcessSelected=false)
|
|
||||||
|
\return the number of changed vertexes (the selected ones)
|
||||||
|
|
||||||
|
There are three possibilities
|
||||||
|
- \c M_LIGHTNESS where lightness = 0.5*(Max(R,G,B)+Min(R,G,B))
|
||||||
|
- \c M_LUMINOSITY where luminosity = 0.21*R+0.71*G+0.7*B
|
||||||
|
- \c M_AVERAGE Plain Average
|
||||||
|
*/
|
||||||
|
static int PerVertexDesaturation(MeshType &m, int method, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
@ -686,9 +687,12 @@ static float ComputeLuminosity(Color4b c)
|
||||||
return float(0.2126f*c[0]+0.7152f*c[1]+0.0722f*c[2]);
|
return float(0.2126f*c[0]+0.7152f*c[1]+0.0722f*c[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Equalize the histogram of colors. It can equalize any combination of rgb channels or
|
/*! \brief Histogram Color Equalization.
|
||||||
//it can work on lightness.
|
\return the number of changed vertexes (the selected ones)
|
||||||
static int Equalize(UpdateMeshType &m, unsigned int rgbMask, const bool ProcessSelected=false)
|
|
||||||
|
Equalize the histogram of colors. It can equalize any combination of rgb channels or it can work on lightness.
|
||||||
|
*/
|
||||||
|
static int PerVertexEqualize(MeshType &m, unsigned int rgbMask, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
//declares , resets and set up 4 histograms, for Red, Green, Blue and Lightness
|
//declares , resets and set up 4 histograms, for Red, Green, Blue and Lightness
|
||||||
Histogramf Hl, Hr, Hg, Hb;
|
Histogramf Hl, Hr, Hg, Hb;
|
||||||
|
@ -757,35 +761,17 @@ static int ValueEqualize(int cdfValue, int cdfMin, int cdfMax)
|
||||||
return int(float((cdfValue - cdfMin)/float(cdfMax - cdfMin)) * 255.0f);
|
return int(float((cdfValue - cdfMin)/float(cdfMax - cdfMin)) * 255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//applies the white balance filter. It may works with an auto regulation of white, or based on a user
|
/*! \brief Simple white balancing filter.
|
||||||
//color that is supposed to be white.
|
\return the number of changed vertexes (the selected ones)
|
||||||
static int WhiteBalance(UpdateMeshType &m, bool automatic, Color4b userColor, const bool ProcessSelected=false)
|
|
||||||
|
It applies a simple white balancing filter. It may works on a provided user color that is supposed to be white.
|
||||||
|
*/
|
||||||
|
static int PerVertexWhiteBalance(MeshType &m, Color4b userColor, const bool ProcessSelected=false)
|
||||||
{
|
{
|
||||||
Color4b unbalancedWhite;
|
Color4b unbalancedWhite= userColor;
|
||||||
float lightness = 0;
|
|
||||||
int counter=0;
|
int counter=0;
|
||||||
VertexIterator vi;
|
VertexIterator vi;
|
||||||
|
|
||||||
if(!automatic) unbalancedWhite = userColor; //no auto regolation required, user has provided a color.
|
|
||||||
else //else, we need to scan the mesh and pick its lighter color...
|
|
||||||
{
|
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
|
||||||
{
|
|
||||||
if(!(*vi).IsD()) //if it has not been deleted...
|
|
||||||
{
|
|
||||||
if(!ProcessSelected || (*vi).IsS()) //if this vertex has been selected...
|
|
||||||
{
|
|
||||||
//the lighter color is selected with an incremental approach...
|
|
||||||
float v = ComputeLightness((*vi).C());
|
|
||||||
if( v > lightness){
|
|
||||||
lightness = v; //save lightness
|
|
||||||
unbalancedWhite = (*vi).C(); //save the color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//in this loop the transformation is applied to the mesh
|
//in this loop the transformation is applied to the mesh
|
||||||
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
for(vi=m.vert.begin();vi!=m.vert.end();++vi) //scan all the vertex...
|
||||||
{
|
{
|
||||||
|
@ -816,39 +802,6 @@ static Color4b ColorWhiteBalance(Color4b c, Color4b unbalancedWhite)
|
||||||
255);
|
255);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PerlinColor(MeshType& m, Box3f bbox, float freq, Point3i channelOffsets)
|
|
||||||
{
|
|
||||||
typedef typename MeshType::ScalarType ScalarType;
|
|
||||||
|
|
||||||
Point3<ScalarType> p;
|
|
||||||
for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
|
|
||||||
{
|
|
||||||
if(!(*vi).IsD()){
|
|
||||||
p = bbox.GlobalToLocal(m.Tr * (*vi).P()); //actual vertex position scaled to bbox
|
|
||||||
(*vi).C() = Color4b( int(255*math::Perlin::Noise(channelOffsets[0]+p[0]*freq,channelOffsets[0]+p[1]*freq,channelOffsets[0]+p[2]*freq)),
|
|
||||||
int(255*math::Perlin::Noise(channelOffsets[1]+p[0]*freq,channelOffsets[1]+p[1]*freq,channelOffsets[1]+p[2]*freq)),
|
|
||||||
int(255*math::Perlin::Noise(channelOffsets[2]+p[0]*freq,channelOffsets[2]+p[1]*freq,channelOffsets[2]+p[2]*freq)),
|
|
||||||
255 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ColorNoise(MeshType& m, int noiseBits)
|
|
||||||
{
|
|
||||||
if(noiseBits>8) noiseBits = 8;
|
|
||||||
if(noiseBits<1) return;
|
|
||||||
|
|
||||||
math::SubtractiveRingRNG randomGen = math::SubtractiveRingRNG(time(NULL));
|
|
||||||
for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
|
|
||||||
{
|
|
||||||
if(!(*vi).IsD()){
|
|
||||||
(*vi).C()[0] = math::Clamp<int>((*vi).C()[0] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
|
||||||
(*vi).C()[1] = math::Clamp<int>((*vi).C()[1] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
|
||||||
(*vi).C()[2] = math::Clamp<int>((*vi).C()[2] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}// end namespace
|
}// end namespace
|
||||||
|
|
|
@ -19,56 +19,6 @@
|
||||||
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
|
||||||
* for more details. *
|
* for more details. *
|
||||||
* *
|
* *
|
||||||
****************************************************************************/
|
|
||||||
/****************************************************************************
|
|
||||||
History
|
|
||||||
|
|
||||||
$Log: not supported by cvs2svn $
|
|
||||||
Revision 1.15 2007/09/21 11:34:10 ponchio
|
|
||||||
Just a clarification comment
|
|
||||||
|
|
||||||
Revision 1.14 2006/06/08 08:52:02 zifnab1974
|
|
||||||
gcc 4 needs the extra template keyword
|
|
||||||
|
|
||||||
Revision 1.13 2005/06/24 12:21:48 ponchio
|
|
||||||
Fixed "lerp" function.
|
|
||||||
|
|
||||||
Revision 1.12 2005/04/14 11:35:09 ponchio
|
|
||||||
*** empty log message ***
|
|
||||||
|
|
||||||
Revision 1.11 2004/09/09 12:51:28 fasano
|
|
||||||
corrected ColorRamp code (template specialization)
|
|
||||||
|
|
||||||
Revision 1.10 2004/09/09 08:39:33 cignoni
|
|
||||||
added a 'template<>' to the specialized constructors from a enum
|
|
||||||
|
|
||||||
Revision 1.9 2004/09/03 13:58:48 fasano
|
|
||||||
Corretto errore sintattico nelle specializzazioni parziali (float e char) di due costruttori di Color4
|
|
||||||
|
|
||||||
Revision 1.8 2004/07/15 11:01:43 ganovelli
|
|
||||||
added inclusion of point3.h
|
|
||||||
|
|
||||||
Revision 1.7 2004/06/24 07:55:50 cignoni
|
|
||||||
Now color ramp can do reverse color ramp
|
|
||||||
|
|
||||||
Revision 1.6 2004/05/26 15:10:29 cignoni
|
|
||||||
Corrected bug in setgrayshade
|
|
||||||
|
|
||||||
Revision 1.5 2004/05/07 12:46:55 cignoni
|
|
||||||
added ifdef for gcc [Bug c++/14479]
|
|
||||||
|
|
||||||
Revision 1.4 2004/05/07 10:06:55 cignoni
|
|
||||||
Corrected template specialization syntax for gcc compiling
|
|
||||||
|
|
||||||
Revision 1.3 2004/03/10 21:38:40 cignoni
|
|
||||||
Written some documentation and added to the space module
|
|
||||||
|
|
||||||
Revision 1.2 2004/03/10 00:35:01 cignoni
|
|
||||||
Removed a wrong (?) copy constructor
|
|
||||||
|
|
||||||
Revision 1.1 2004/02/10 01:11:28 cignoni
|
|
||||||
Edited Comments and GPL license
|
|
||||||
|
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef __VCGLIB_COLOR4
|
#ifndef __VCGLIB_COLOR4
|
||||||
|
@ -94,17 +44,17 @@ public:
|
||||||
/// Constant for storing standard colors.
|
/// Constant for storing standard colors.
|
||||||
/// Each color is stored in a simple in so that the bit pattern match with the one of Color4b.
|
/// Each color is stored in a simple in so that the bit pattern match with the one of Color4b.
|
||||||
enum ColorConstant {
|
enum ColorConstant {
|
||||||
Black =0xff000000,
|
Black = 0xff000000,
|
||||||
Gray =0xff808080,
|
Gray = 0xff808080,
|
||||||
White =0xffffffff,
|
White = 0xffffffff,
|
||||||
|
|
||||||
Red =0xff0000ff,
|
Red = 0xff0000ff,
|
||||||
Green =0xff00ff00,
|
Green = 0xff00ff00,
|
||||||
Blue =0xffff0000,
|
Blue = 0xffff0000,
|
||||||
|
|
||||||
Cyan =0xffffff00,
|
Cyan = 0xffffff00,
|
||||||
Yellow =0xff00ffff,
|
Yellow = 0xff00ffff,
|
||||||
Magenta=0xffff00ff,
|
Magenta = 0xffff00ff,
|
||||||
|
|
||||||
LightGray =0xffc0c0c0,
|
LightGray =0xffc0c0c0,
|
||||||
LightRed =0xff8080ff,
|
LightRed =0xff8080ff,
|
||||||
|
@ -117,18 +67,10 @@ public:
|
||||||
DarkBlue =0xff400000
|
DarkBlue =0xff400000
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Color4 ( const T nx, const T ny, const T nz , const T nw ) :Point4<T>(nx,ny,nz,nw) {};
|
inline Color4 ( const T nx, const T ny, const T nz , const T nw ) :Point4<T>(nx,ny,nz,nw) {}
|
||||||
// inline Color4 ( Color4 &c) :Point4<T>(c) {};
|
inline Color4 ( const Point4<T> &c) :Point4<T>(c) {}
|
||||||
inline Color4 ( const Point4<T> &c) :Point4<T>(c) {};
|
inline Color4 (){}
|
||||||
inline Color4 (){};
|
|
||||||
inline Color4 (ColorConstant cc);
|
inline Color4 (ColorConstant cc);
|
||||||
#ifdef VCG_USE_EIGEN
|
|
||||||
template<typename OtherDerived>
|
|
||||||
inline Color4 (const Eigen::MatrixBase<OtherDerived>& other) : Base(other)
|
|
||||||
{
|
|
||||||
// TODO make sure the types are the same
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <class Q>
|
template <class Q>
|
||||||
inline void Import(const Color4<Q> & b )
|
inline void Import(const Color4<Q> & b )
|
||||||
|
@ -163,19 +105,49 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void lerp(const Color4 &c0, const Color4 &c1, const float x);
|
inline void lerp(const Color4 &c0, const Color4 &c1, const float x)
|
||||||
inline void lerp(const Color4 &c0, const Color4 &c1, const Color4 &c2, const Point3f &ip);
|
|
||||||
/// given a float and a range set the corresponding color in the well known red->green->blue color ramp. To reverse the direction of the ramp just swap minf and maxf.
|
|
||||||
inline void SetColorRamp(const float &minf,const float &maxf ,float v );
|
|
||||||
inline void SetRGB( unsigned char r, unsigned char g, unsigned char b )
|
|
||||||
{
|
{
|
||||||
(*this)[0] = r;
|
assert(x>=0);
|
||||||
(*this)[1] = g;
|
assert(x<=1);
|
||||||
(*this)[2] = b;
|
|
||||||
(*this)[3] = 0;
|
(*this)[0]=(T)(c1.V()[0]*x + c0.V()[0]*(1.0f-x));
|
||||||
|
(*this)[1]=(T)(c1.V()[1]*x + c0.V()[1]*(1.0f-x));
|
||||||
|
(*this)[2]=(T)(c1.V()[2]*x + c0.V()[2]*(1.0f-x));
|
||||||
|
(*this)[3]=(T)(c1.V()[3]*x + c0.V()[3]*(1.0f-x));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHSVColor( float h, float s, float v){
|
inline void lerp(const Color4 &c0, const Color4 &c1, const Color4 &c2, const Point3f &ip)
|
||||||
|
{
|
||||||
|
assert(fabs(ip[0]+ip[1]+ip[2]-1)<0.00001);
|
||||||
|
|
||||||
|
(*this)[0]=(T)(c0[0]*ip[0] + c1[0]*ip[1]+ c2[0]*ip[2]);
|
||||||
|
(*this)[1]=(T)(c0[1]*ip[0] + c1[1]*ip[1]+ c2[1]*ip[2]);
|
||||||
|
(*this)[2]=(T)(c0[2]*ip[0] + c1[2]*ip[1]+ c2[2]*ip[2]);
|
||||||
|
(*this)[3]=(T)(c0[3]*ip[0] + c1[3]*ip[1]+ c2[3]*ip[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// given a float and a range set the corresponding color in the well known red->green->blue color ramp. To reverse the direction of the ramp just swap minf and maxf.
|
||||||
|
inline void SetColorRamp(const float &minf,const float &maxf ,float v )
|
||||||
|
{
|
||||||
|
if(minf>maxf) { SetColorRamp(maxf,minf,maxf+(minf-v)); return; }
|
||||||
|
|
||||||
|
float step=(maxf-minf)/4;
|
||||||
|
if(v < minf ) { *this=Color4<T>(Color4<T>::Red); return; }
|
||||||
|
v-=minf;
|
||||||
|
if(v<step) { lerp(Color4<T>(Color4<T>::Red), Color4<T>(Color4<T>::Yellow),v/step); return;}
|
||||||
|
v-=step;
|
||||||
|
if(v<step) { lerp(Color4<T>(Color4<T>::Yellow),Color4<T>(Color4<T>::Green), v/step); return;}
|
||||||
|
v-=step;
|
||||||
|
if(v<step) { lerp(Color4<T>(Color4<T>::Green), Color4<T>(Color4<T>::Cyan), v/step); return;}
|
||||||
|
v-=step;
|
||||||
|
if(v<step) { lerp(Color4<T>(Color4<T>::Cyan), Color4<T>(Color4<T>::Blue), v/step); return;}
|
||||||
|
|
||||||
|
*this= Color4<T>(Color4<T>::Blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetHSVColor( float h, float s, float v)
|
||||||
|
{
|
||||||
float r,g,b;
|
float r,g,b;
|
||||||
if(s==0.0){ // gray color
|
if(s==0.0){ // gray color
|
||||||
r = g = b = v;
|
r = g = b = v;
|
||||||
|
@ -194,7 +166,8 @@ public:
|
||||||
float q = v*(1.0f-s*f);
|
float q = v*(1.0f-s*f);
|
||||||
float t = v*(1.0f-s*(1.0f-f));
|
float t = v*(1.0f-s*(1.0f-f));
|
||||||
|
|
||||||
switch(i){
|
switch(i)
|
||||||
|
{
|
||||||
case 0: r=v; g=t; b=p; break;
|
case 0: r=v; g=t; b=p; break;
|
||||||
case 1: r=q; g=v; b=p; break;
|
case 1: r=q; g=v; b=p; break;
|
||||||
case 2: r=p; g=v; b=t; break;
|
case 2: r=p; g=v; b=t; break;
|
||||||
|
@ -207,8 +180,7 @@ public:
|
||||||
(*this)[1]=(unsigned char)(255*g);
|
(*this)[1]=(unsigned char)(255*g);
|
||||||
(*this)[2]=(unsigned char)(255*b);
|
(*this)[2]=(unsigned char)(255*b);
|
||||||
(*this)[3]=255;
|
(*this)[3]=255;
|
||||||
// V()[0]=r*256;V()[1]=g*256;V()[2]=b*256;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline static Color4 GrayShade(float f)
|
inline static Color4 GrayShade(float f)
|
||||||
{
|
{
|
||||||
|
@ -255,55 +227,8 @@ inline static Color4 ColorRamp(const float &minf,const float &maxf ,float v )
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template <class T>
|
|
||||||
inline void Color4<T>::lerp(const Color4<T> &c0, const Color4<T> &c1, const float x)
|
|
||||||
{
|
|
||||||
assert(x>=0);
|
|
||||||
assert(x<=1);
|
|
||||||
|
|
||||||
(*this)[0]=(T)(c1.V()[0]*x + c0.V()[0]*(1.0f-x));
|
template <> template <>
|
||||||
(*this)[1]=(T)(c1.V()[1]*x + c0.V()[1]*(1.0f-x));
|
|
||||||
(*this)[2]=(T)(c1.V()[2]*x + c0.V()[2]*(1.0f-x));
|
|
||||||
(*this)[3]=(T)(c1.V()[3]*x + c0.V()[3]*(1.0f-x));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void Color4<T>::lerp(const Color4<T> &c0, const Color4<T> &c1, const Color4<T> &c2, const Point3f &ip)
|
|
||||||
{
|
|
||||||
assert(fabs(ip[0]+ip[1]+ip[2]-1)<0.00001);
|
|
||||||
|
|
||||||
(*this)[0]=(T)(c0[0]*ip[0] + c1[0]*ip[1]+ c2[0]*ip[2]);
|
|
||||||
(*this)[1]=(T)(c0[1]*ip[0] + c1[1]*ip[1]+ c2[1]*ip[2]);
|
|
||||||
(*this)[2]=(T)(c0[2]*ip[0] + c1[2]*ip[1]+ c2[2]*ip[2]);
|
|
||||||
(*this)[3]=(T)(c0[3]*ip[0] + c1[3]*ip[1]+ c2[3]*ip[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void Color4<T>::SetColorRamp(const float &minf,const float &maxf ,float v )
|
|
||||||
{
|
|
||||||
if(minf>maxf) { SetColorRamp(maxf,minf,maxf+(minf-v)); return; }
|
|
||||||
if(v < minf ) { *this=Color4<T>(Color4<T>::Red); return; }
|
|
||||||
//the case v > maxf is handled automatically at the end of the function
|
|
||||||
|
|
||||||
float step=(maxf-minf)/4;
|
|
||||||
v-=minf;
|
|
||||||
if(v<step) {lerp(Color4<T>(Color4<T>::Red), Color4<T>(Color4<T>::Yellow),v/step); return;}
|
|
||||||
v-=step;
|
|
||||||
if(v<step) {lerp(Color4<T>(Color4<T>::Yellow),Color4<T>(Color4<T>::Green),v/step);return;}
|
|
||||||
v-=step;
|
|
||||||
if(v<step) {lerp(Color4<T>(Color4<T>::Green),Color4<T>(Color4<T>::Cyan),v/step); return;}
|
|
||||||
v-=step;
|
|
||||||
if(v<step) {lerp(Color4<T>(Color4<T>::Cyan),Color4<T>(Color4<T>::Blue),v/step); return;}
|
|
||||||
|
|
||||||
*this= Color4<T>(Color4<T>::Blue);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 3)
|
|
||||||
template <>
|
|
||||||
#endif
|
|
||||||
template <>
|
|
||||||
inline void Color4<float>::Import(const Color4<unsigned char> &b)
|
inline void Color4<float>::Import(const Color4<unsigned char> &b)
|
||||||
{
|
{
|
||||||
(*this)[0]=b[0]/255.0f;
|
(*this)[0]=b[0]/255.0f;
|
||||||
|
@ -312,10 +237,7 @@ inline void Color4<float>::Import(const Color4<unsigned char> &b)
|
||||||
(*this)[3]=b[3]/255.0f;
|
(*this)[3]=b[3]/255.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 3)
|
template <> template <>
|
||||||
template <> // [Bug c++/14479] enum definition in template class with template methods causes error.
|
|
||||||
#endif
|
|
||||||
template <>
|
|
||||||
inline void Color4<unsigned char>::Import(const Color4<float> &b)
|
inline void Color4<unsigned char>::Import(const Color4<float> &b)
|
||||||
{
|
{
|
||||||
(*this)[0]=(unsigned char)(b[0]*255.0f);
|
(*this)[0]=(unsigned char)(b[0]*255.0f);
|
||||||
|
@ -324,10 +246,7 @@ inline void Color4<unsigned char>::Import(const Color4<float> &b)
|
||||||
(*this)[3]=(unsigned char)(b[3]*255.0f);
|
(*this)[3]=(unsigned char)(b[3]*255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 3)
|
template <> template <>
|
||||||
template <> // [Bug c++/14479] enum definition in template class with template methods causes error.
|
|
||||||
#endif
|
|
||||||
template <>
|
|
||||||
inline void Color4<unsigned char>::Import(const Point4<float> &b)
|
inline void Color4<unsigned char>::Import(const Point4<float> &b)
|
||||||
{
|
{
|
||||||
(*this)[0]=(unsigned char)(b[0]*255.0f);
|
(*this)[0]=(unsigned char)(b[0]*255.0f);
|
||||||
|
@ -336,10 +255,7 @@ inline void Color4<unsigned char>::Import(const Point4<float> &b)
|
||||||
(*this)[3]=(unsigned char)(b[3]*255.0f);
|
(*this)[3]=(unsigned char)(b[3]*255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 3)
|
template <> template <>
|
||||||
template <>
|
|
||||||
#endif
|
|
||||||
template <>
|
|
||||||
inline Color4<unsigned char> Color4<unsigned char>::Construct( const Color4<float> & b )
|
inline Color4<unsigned char> Color4<unsigned char>::Construct( const Color4<float> & b )
|
||||||
{
|
{
|
||||||
return Color4<unsigned char>(
|
return Color4<unsigned char>(
|
||||||
|
@ -349,10 +265,7 @@ inline Color4<unsigned char> Color4<unsigned char>::Construct( const Color4<floa
|
||||||
(unsigned char)(b[3]*255.0f));
|
(unsigned char)(b[3]*255.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__GNUC__) || (__GNUC__ > 3)
|
template <> template <>
|
||||||
template <>
|
|
||||||
#endif
|
|
||||||
template <>
|
|
||||||
inline Color4<float> Color4<float>::Construct( const Color4<unsigned char> & b )
|
inline Color4<float> Color4<float>::Construct( const Color4<unsigned char> & b )
|
||||||
{
|
{
|
||||||
return Color4<float>(
|
return Color4<float>(
|
||||||
|
@ -362,15 +275,6 @@ inline Color4<float> Color4<float>::Construct( const Color4<unsigned char> & b )
|
||||||
(float)(b[3])/255.0f);
|
(float)(b[3])/255.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//template <class T,class S>
|
|
||||||
//inline void Color4<T>::Import(const Color4<S> &b)
|
|
||||||
//{
|
|
||||||
// V()[0] = T(b[0]);
|
|
||||||
// V()[1] = T(b[1]);
|
|
||||||
// V()[2] = T(b[2]);
|
|
||||||
// V()[3] = T(b[3]);
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
template<>
|
template<>
|
||||||
inline Color4<unsigned char>::Color4(Color4<unsigned char>::ColorConstant cc)
|
inline Color4<unsigned char>::Color4(Color4<unsigned char>::ColorConstant cc)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue