19 #include <Eigen/Dense> 31 bool enableTransparency,
float m_xMin_p,
float m_xMax_p,
float m_yMin_p,
33 : m_enableTransparency(enableTransparency),
45 enableTextureLinearInterpolation(
true);
73 const auto cols = Z.cols();
74 const auto rows = Z.rows();
77 if (cols == 0 && rows == 0)
return;
84 vertex_normals.assign(
85 (1 + cols) * (1 + rows),
86 std::pair<TPoint3D, size_t>(
TPoint3D(0, 0, 0), 0));
88 if (m_colorFromZ || m_isImage) updateColorsMatrix();
91 if (mask.cols() != 0 && mask.rows() != 0)
93 ASSERT_(mask.cols() == cols && mask.rows() == rows);
96 const float sCellX = (m_xMax - m_xMin) / (rows - 1);
97 const float sCellY = (m_yMax - m_yMin) / (cols - 1);
101 for (
int iX = 0; iX < rows - 1; iX++)
102 for (
int iY = 0; iY < cols - 1; iY++)
104 if (useMask && (!mask(iX, iY) || !mask(iX + 1, iY + 1)))
continue;
105 tri.
x(0) = m_xMin + iX * sCellX;
106 tri.
y(0) = m_yMin + iY * sCellY;
107 tri.
z(0) = Z(iX, iY);
108 tri.
x(2) = tri.
x(0) + sCellX;
109 tri.
y(2) = tri.
y(0) + sCellY;
110 tri.
z(2) = Z(iX + 1, iY + 1);
114 tvi.
vind[0] = iX + rows * iY;
115 tvi.
vind[2] = (iX + 1) + rows * (iY + 1);
123 if (!useMask || mask(iX + 1, iY))
127 tri.
z(1) = Z(iX + 1, iY);
129 for (
int i = 0; i < 3; i++) tri.
a(i) = m_color.A;
134 colormap(m_colorMap, C(iX, iY), col.
R, col.
G, col.
B);
138 colormap(m_colorMap, C(iX + 1, iY), col.
R, col.
G, col.
B);
143 m_colorMap, C(iX + 1, iY + 1), col.
R, col.
G, col.
B);
150 if (getTextureImage().isColor())
152 tri.
r(0) = tri.
r(1) = tri.
r(2) = C_r(iX, iY);
153 tri.
g(0) = tri.
g(1) = tri.
g(2) = C_g(iX, iY);
154 tri.
b(0) = tri.
b(1) = tri.
b(2) = C_b(iX, iY);
158 tri.
r(0) = tri.
r(1) = tri.
r(2) = C(iX, iY);
159 tri.
g(0) = tri.
g(1) = tri.
g(2) = C(iX, iY);
160 tri.
b(0) = tri.
b(1) = tri.
b(2) = C(iX, iY);
165 tri.
r(0) = tri.
r(1) = tri.
r(2) = m_color.R / 255.f;
166 tri.
g(0) = tri.
g(1) = tri.
g(2) = m_color.G / 255.f;
167 tri.
b(0) = tri.
b(1) = tri.
b(2) = m_color.B / 255.f;
173 float ax = tri.
x(1) - tri.
x(0);
174 float bx = tri.
x(2) - tri.
x(0);
175 float ay = tri.
y(1) - tri.
y(0);
176 float by = tri.
y(2) - tri.
y(0);
177 float az = tri.
z(1) - tri.
z(0);
178 float bz = tri.
z(2) - tri.
z(0);
180 ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx);
183 tvi.
vind[1] = iX + 1 + rows * iY;
186 actualMesh.emplace_back(tri, tvi);
189 for (
unsigned long k : tvi.
vind)
191 vertex_normals[k].first += this_normal;
192 vertex_normals[k].second++;
201 if (!useMask || mask(iX, iY + 1))
209 tri.
z(2) = Z(iX, iY + 1);
214 colormap(m_colorMap, C(iX, iY), col.
R, col.
G, col.
B);
219 m_colorMap, C(iX + 1, iY + 1), col.
R, col.
G, col.
B);
223 colormap(m_colorMap, C(iX, iY + 1), col.
R, col.
G, col.
B);
230 if (getTextureImage().isColor())
232 tri.
r(0) = tri.
r(1) = tri.
r(2) = C_r(iX, iY);
233 tri.
g(0) = tri.
g(1) = tri.
g(2) = C_g(iX, iY);
234 tri.
b(0) = tri.
b(1) = tri.
b(2) = C_b(iX, iY);
238 tri.
r(0) = tri.
r(1) = tri.
r(2) = C(iX, iY);
239 tri.
g(0) = tri.
g(1) = tri.
g(2) = C(iX, iY);
240 tri.
b(0) = tri.
b(1) = tri.
b(2) = C(iX, iY);
245 tri.
r(0) = tri.
r(1) = tri.
r(2) = m_color.R / 255.f;
246 tri.
g(0) = tri.
g(1) = tri.
g(2) = m_color.G / 255.f;
247 tri.
b(0) = tri.
b(1) = tri.
b(2) = m_color.B / 255.f;
253 float ax = tri.
x(1) - tri.
x(0);
254 float bx = tri.
x(2) - tri.
x(0);
255 float ay = tri.
y(1) - tri.
y(0);
256 float by = tri.
y(2) - tri.
y(0);
257 float az = tri.
z(1) - tri.
z(0);
258 float bz = tri.
z(2) - tri.
z(0);
260 ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx);
264 tvi.
vind[2] = iX + rows * (iY + 1);
267 actualMesh.emplace_back(tri, tvi);
270 for (
unsigned long k : tvi.
vind)
272 vertex_normals[k].first += this_normal;
273 vertex_normals[k].second++;
279 for (
auto& vertex_normal : vertex_normals)
281 const size_t N = vertex_normal.second;
284 vertex_normal.first *= 1.0 / N;
285 vertex_normal.first = vertex_normal.first.
unitarize();
289 m_trianglesUpToDate =
true;
290 m_polygonsUpToDate =
false;
308 if (!m_trianglesUpToDate) updateTriangles();
321 for (
auto& i : actualMesh)
325 for (
int kk = 0; kk <= 3; kk++)
328 int k1 = (kk + 1) % 3;
330 vbd.emplace_back(t.
x(k), t.
y(k), t.
z(k));
331 cbd.emplace_back(t.
r(k), t.
g(k), t.
b(k), t.
a(k));
333 vbd.emplace_back(t.
x(k1), t.
y(k1), t.
z(k1));
334 cbd.emplace_back(t.
r(k1), t.
g(k1), t.
b(k1), t.
a(k1));
344 for (
auto& i : actualMesh)
349 const auto& n0 = vertex_normals.at(tvi.
vind[0]).first;
350 const auto& n1 = vertex_normals.at(tvi.
vind[1]).first;
351 const auto& n2 = vertex_normals.at(tvi.
vind[2]).first;
356 tri.vertices[1].normal = n1;
357 tri.vertices[2].normal = n2;
359 for (
int k = 0; k < 3; k++)
361 tri.vertices[k].uv.x =
362 (tri.vertices[k].xyzrgba.pt.x - m_xMin) / (m_xMax - m_xMin);
363 tri.vertices[k].uv.y =
364 (tri.vertices[k].xyzrgba.pt.y - m_yMin) / (m_yMax - m_yMin);
367 tris.emplace_back(std::move(tri));
384 m_modified_Image =
true;
385 m_enableTransparency =
false;
386 m_colorFromZ =
false;
388 m_trianglesUpToDate =
false;
409 m_modified_Image =
true;
410 m_enableTransparency =
false;
411 m_colorFromZ =
false;
413 m_trianglesUpToDate =
false;
423 writeToStreamRender(
out);
424 writeToStreamTexturedObject(
out);
427 out << m_xMin << m_xMax << m_yMin << m_yMax;
429 out << m_enableTransparency;
432 out << m_isWireFrame;
433 out << int16_t(m_colorMap);
443 readFromStreamRender(in);
444 readFromStreamTexturedObject(in);
452 in >> m_enableTransparency;
463 m_isWireFrame =
false;
467 m_trianglesUpToDate =
false;
472 m_trianglesUpToDate =
false;
478 if ((!m_modified_Z) && (!m_modified_Image))
return;
484 const int cols = getTextureImage().getWidth();
485 const int rows = getTextureImage().getHeight();
487 if ((cols != Z.cols()) || (rows != Z.rows()))
488 printf(
"\nTexture Image and Z sizes have to be equal");
490 else if (getTextureImage().isColor())
492 C_r.setSize(rows, cols);
493 C_g.setSize(rows, cols);
494 C_b.setSize(rows, cols);
495 getTextureImage().getAsRGBMatrices(C_r, C_g, C_b);
499 C.setSize(rows, cols);
500 getTextureImage().getAsMatrix(C);
505 const size_t cols = Z.cols();
506 const size_t rows = Z.rows();
507 C.setSize(rows, cols);
518 float val_max = -std::numeric_limits<float>::max(),
519 val_min = std::numeric_limits<float>::max();
520 bool any_valid =
false;
522 for (
size_t c = 0; c < cols; c++)
523 for (
size_t r = 0; r < rows; r++)
525 if (!mask(r, c))
continue;
527 const float val = C(r, c);
534 float minMaxDelta = val_max - val_min;
535 if (minMaxDelta == 0) minMaxDelta = 1;
536 const float minMaxDelta_ = 1.0f / minMaxDelta;
537 C.array() = (C.array() - val_min) * minMaxDelta_;
542 m_modified_Image =
false;
543 m_modified_Z =
false;
544 m_trianglesUpToDate =
false;
551 m_trianglesUpToDate =
false;
562 m_trianglesUpToDate =
false;
568 if (!m_trianglesUpToDate || !m_polygonsUpToDate) updatePolygons();
574 const std::pair<mrpt::opengl::TTriangle, CMesh::TTriangleVertexIndices>& p)
583 if (!m_trianglesUpToDate) updateTriangles();
584 size_t N = actualMesh.size();
587 actualMesh.begin(), actualMesh.end(), tmpPolys.begin(),
589 m_polygonsUpToDate =
true;
612 const float ycenter = 0.5f * (m_yMin + m_yMax);
613 const float xwidth = m_xMax - m_xMin;
614 const float newratio = float(getTextureImage().getWidth()) /
616 m_yMax = ycenter + 0.5f * newratio * xwidth;
617 m_yMin = ycenter - 0.5f * newratio * xwidth;
virtual ~CMesh() override
mrpt::math::TPoint3Df & vertex(size_t i)
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
void colormap(const TColormap &color_map, const float color_index, float &r, float &g, float &b)
Transform a float number in the range [0,1] into RGB components.
TColormap
Different colormaps for use in mrpt::img::colormap()
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.
const uint8_t & b(size_t i) const
void assignImageAndZ(const mrpt::img::CImage &img, const mrpt::math::CMatrixDynamic< float > &in_Z)
Assigns a texture image and Z simultaneously, and disable transparency.
static constexpr shader_id_t TEXTURED_TRIANGLES
uint8_t serializeGetVersion() const override
Must return the current versioning number of the object.
bool traceRay(const std::vector< TPolygonWithPlane > &vec, const mrpt::math::TPose3D &pose, double &dist)
Fast ray tracing method using polygons' properties.
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
To be added to all CSerializable-classes implementation files.
const uint8_t & r(size_t i) const
void notifyChange() const
Call to enable calling renderUpdateBuffers() before the next render() rendering iteration.
const float & x(size_t i) const
A triangle (float coordinates) with RGBA colors (u8) and UV (texture coordinates) for each vertex...
Slightly heavyweight type to speed-up calculations with polygons in 3D.
mrpt::opengl::shader_id_t shader_id
This file implements several operations that operate element-wise on individual or pairs of container...
void serializeFrom(mrpt::serialization::CArchive &in, uint8_t serial_version) override
Pure virtual method for reading (deserializing) from an abstract archive.
The base class of 3D objects that can be directly rendered through OpenGL.
const uint8_t & g(size_t i) const
size_t getHeight() const override
Returns the height of the image in pixels.
void setMask(const mrpt::math::CMatrixDynamic< float > &in_mask)
This method sets the boolean mask of valid heights for each position (cell) in the mesh grid...
Context for calls to render()
std::vector< mrpt::math::TPoint3Df > m_vertex_buffer_data
void assignImage(const mrpt::img::CImage &img)
Assigns a texture image.
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
const uint8_t & a(size_t i) const
void serializeTo(mrpt::serialization::CArchive &out) const override
Pure virtual method for writing (serializing) to an abstract archive.
std::array< Vertex, 3 > vertices
#define ASSERT_(f)
Defines an assertion mechanism.
This base provides a set of functions for maths stuff.
size_t getWidth() const override
Returns the width of the image in pixels.
void normalize(CONTAINER &c, Scalar valMin, Scalar valMax)
Scales all elements such as the minimum & maximum values are shifted to the given values...
static constexpr shader_id_t WIREFRAME
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
bool traceRay(const mrpt::poses::CPose3D &o, double &dist) const override
Trace ray.
TPoint3D_< double > TPoint3D
Lightweight 3D point.
void updatePolygons() const
mrpt::math::TPolygonWithPlane createPolygonFromTriangle(const std::pair< mrpt::opengl::TTriangle, CMesh::TTriangleVertexIndices > &p)
size_type rows() const
Number of rows in the matrix.
size_type cols() const
Number of columns in the matrix.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
void setZ(const mrpt::math::CMatrixDynamic< float > &in_Z)
This method sets the matrix of heights for each position (cell) in the mesh grid. ...
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
TPoint3D_< T > unitarize() const
Returns this vector with unit length: v/norm(v)
std::vector< mrpt::img::TColor > m_color_buffer_data
uint8_t f2u8(const float f)
converts a float [0,1] into an uint8_t [0,255] (without checking for out of bounds) ...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
const float & y(size_t i) const
Virtual base class for "archives": classes abstracting I/O streams.
void getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const override
Evaluates the bounding box of this object (including possible children) in the coordinate frame of th...
void onUpdateBuffers_Wireframe() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
mrpt::vision::TStereoCalibResults out
const float & z(size_t i) const
#define ASSERT_ABOVE_(__A, __B)
An RGBA color - floats in the range [0,1].
The namespace for 3D scene representation and rendering.
void updateColorsMatrix() const
Called internally to assure C is updated.
void adjustGridToImageAR()
Adjust grid limits according to the image aspect ratio, maintaining the X limits and resizing in the ...
void onUpdateBuffers_TexturedTriangles() override
Must be implemented in derived classes to update the geometric entities to be drawn in "m_*_buffer" f...
A planar (XY) grid where each cell has an associated height and, optionally, a texture map...
std::vector< mrpt::opengl::TTriangle > m_triangles
List of triangles.
double getHeight(const TPolygon3D &p, const TPoint3D &c)
This template class provides the basic functionality for a general 2D any-size, resizable container o...
void render(const RenderContext &rc) const override
Implements the rendering of 3D objects in each class derived from CRenderizable.
static math::TPolygon3D tmpPoly(3)
void updateTriangles() const
Called internally to assure the triangle list is updated.
void assignImage(const mrpt::img::CImage &img, const mrpt::img::CImage &imgAlpha)
Assigns a texture and a transparency image, and enables transparency (If the images are not 2^N x 2^M...
3D polygon, inheriting from std::vector<TPoint3D>
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.
A class for storing images as grayscale or RGB bitmaps.
void renderUpdateBuffers() const override
Called whenever m_outdatedBuffers is true: used to re-generate OpenGL vertex buffers, etc.