Open3D (C++ API)  0.17.0
Loading...
Searching...
No Matches
TriangleMesh.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2023 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7
8#pragma once
9
10#include <list>
11
12#include "open3d/core/Tensor.h"
19
20namespace open3d {
21namespace t {
22namespace geometry {
23
24class LineSet;
25
92class TriangleMesh : public Geometry, public DrawableGeometry {
93public:
97 TriangleMesh(const core::Device &device = core::Device("CPU:0"));
98
107 TriangleMesh(const core::Tensor &vertex_positions,
108 const core::Tensor &triangle_indices);
109
110 virtual ~TriangleMesh() override {}
111
112public:
114 std::string ToString() const;
115
121 TriangleMesh To(const core::Device &device, bool copy = false) const;
122
124 TriangleMesh Clone() const { return To(GetDevice(), /*copy=*/true); }
125
127 const TensorMap &GetVertexAttr() const { return vertex_attr_; }
128
131
136 core::Tensor &GetVertexAttr(const std::string &key) {
137 return vertex_attr_.at(key);
138 }
139
143
147
151
153 const TensorMap &GetTriangleAttr() const { return triangle_attr_; }
154
157
162 core::Tensor &GetTriangleAttr(const std::string &key) {
163 return triangle_attr_.at(key);
164 }
165
169
173
177
181 const core::Tensor &GetVertexAttr(const std::string &key) const {
182 return vertex_attr_.at(key);
183 }
184
189 void RemoveVertexAttr(const std::string &key) { vertex_attr_.Erase(key); }
190
194 return GetVertexAttr("positions");
195 }
196
200 return GetVertexAttr("colors");
201 }
202
206 return GetVertexAttr("normals");
207 }
208
213 const core::Tensor &GetTriangleAttr(const std::string &key) const {
214 return triangle_attr_.at(key);
215 }
216
221 void RemoveTriangleAttr(const std::string &key) {
223 }
224
228 return GetTriangleAttr("indices");
229 }
230
234 return GetTriangleAttr("normals");
235 }
236
240 return GetTriangleAttr("colors");
241 }
242
248 void SetVertexAttr(const std::string &key, const core::Tensor &value) {
249 core::AssertTensorDevice(value, device_);
250 vertex_attr_[key] = value;
251 }
252
255 void SetVertexPositions(const core::Tensor &value) {
256 core::AssertTensorShape(value, {utility::nullopt, 3});
257 SetVertexAttr("positions", value);
258 }
259
262 void SetVertexColors(const core::Tensor &value) {
263 core::AssertTensorShape(value, {utility::nullopt, 3});
264 SetVertexAttr("colors", value);
265 }
266
269 void SetVertexNormals(const core::Tensor &value) {
270 core::AssertTensorShape(value, {utility::nullopt, 3});
271 SetVertexAttr("normals", value);
272 }
273
279 void SetTriangleAttr(const std::string &key, const core::Tensor &value) {
280 core::AssertTensorDevice(value, device_);
281 triangle_attr_[key] = value;
282 }
283
285 void SetTriangleIndices(const core::Tensor &value) {
286 core::AssertTensorShape(value, {utility::nullopt, 3});
287 SetTriangleAttr("indices", value);
288 }
289
292 void SetTriangleNormals(const core::Tensor &value) {
293 core::AssertTensorShape(value, {utility::nullopt, 3});
294 SetTriangleAttr("normals", value);
295 }
296
299 void SetTriangleColors(const core::Tensor &value) {
300 core::AssertTensorShape(value, {utility::nullopt, 3});
301 SetTriangleAttr("colors", value);
302 }
303
308 bool HasVertexAttr(const std::string &key) const {
309 return vertex_attr_.Contains(key) &&
310 GetVertexAttr(key).GetLength() > 0 &&
311 GetVertexAttr(key).GetLength() ==
313 }
314
317 bool HasVertexPositions() const { return HasVertexAttr("positions"); }
318
324 bool HasVertexColors() const { return HasVertexAttr("colors"); }
325
331 bool HasVertexNormals() const { return HasVertexAttr("normals"); }
332
337 bool HasTriangleAttr(const std::string &key) const {
338 return triangle_attr_.Contains(key) &&
339 GetTriangleAttr(key).GetLength() > 0 &&
340 GetTriangleAttr(key).GetLength() ==
342 }
343
347 bool HasTriangleIndices() const { return HasTriangleAttr("indices"); }
348
354 bool HasTriangleNormals() const { return HasTriangleAttr("normals"); }
355
361 bool HasTriangleColors() const { return HasTriangleAttr("colors"); }
362
373 static TriangleMesh CreateBox(
374 double width = 1.0,
375 double height = 1.0,
376 double depth = 1.0,
377 core::Dtype float_dtype = core::Float32,
378 core::Dtype int_dtype = core::Int64,
379 const core::Device &device = core::Device("CPU:0"));
380
395 double radius = 1.0,
396 int resolution = 20,
397 core::Dtype float_dtype = core::Float32,
398 core::Dtype int_dtype = core::Int64,
399 const core::Device &device = core::Device("CPU:0"));
400
411 double radius = 1.0,
412 core::Dtype float_dtype = core::Float32,
413 core::Dtype int_dtype = core::Int64,
414 const core::Device &device = core::Device("CPU:0"));
415
426 double radius = 1.0,
427 core::Dtype float_dtype = core::Float32,
428 core::Dtype int_dtype = core::Int64,
429 const core::Device &device = core::Device("CPU:0"));
430
441 double radius = 1.0,
442 core::Dtype float_dtype = core::Float32,
443 core::Dtype int_dtype = core::Int64,
444 const core::Device &device = core::Device("CPU:0"));
445
459 double radius = 1.0,
460 double height = 2.0,
461 int resolution = 20,
462 int split = 4,
463 core::Dtype float_dtype = core::Float32,
464 core::Dtype int_dtype = core::Int64,
465 const core::Device &device = core::Device("CPU:0"));
466
480 double radius = 1.0,
481 double height = 2.0,
482 int resolution = 20,
483 int split = 1,
484 core::Dtype float_dtype = core::Float32,
485 core::Dtype int_dtype = core::Int64,
486 const core::Device &device = core::Device("CPU:0"));
487
502 double torus_radius = 1.0,
503 double tube_radius = 0.5,
504 int radial_resolution = 30,
505 int tubular_resolution = 20,
506 core::Dtype float_dtype = core::Float32,
507 core::Dtype int_dtype = core::Int64,
508 const core::Device &device = core::Device("CPU:0"));
509
528 double cylinder_radius = 1.0,
529 double cone_radius = 1.5,
530 double cylinder_height = 5.0,
531 double cone_height = 4.0,
532 int resolution = 20,
533 int cylinder_split = 4,
534 int cone_split = 1,
535 core::Dtype float_dtype = core::Float32,
536 core::Dtype int_dtype = core::Int64,
537 const core::Device &device = core::Device("CPU:0"));
538
548 double size = 1.0,
549 const Eigen::Vector3d &origin = Eigen::Vector3d(0.0, 0.0, 0.0),
550 core::Dtype float_dtype = core::Float32,
551 core::Dtype int_dtype = core::Int64,
552 const core::Device &device = core::Device("CPU:0"));
553
570 int length_split = 70,
571 int width_split = 15,
572 int twists = 1,
573 double radius = 1,
574 double flatness = 1,
575 double width = 1,
576 double scale = 1,
577 core::Dtype float_dtype = core::Float32,
578 core::Dtype int_dtype = core::Int64,
579 const core::Device &device = core::Device("CPU:0"));
580
591 const std::string &text,
592 double depth = 0.0,
593 core::Dtype float_dtype = core::Float32,
594 core::Dtype int_dtype = core::Int64,
595 const core::Device &device = core::Device("CPU:0"));
596
597public:
599 TriangleMesh &Clear() override {
600 vertex_attr_.clear();
601 triangle_attr_.clear();
602 return *this;
603 }
604
606 bool IsEmpty() const override { return !HasVertexPositions(); }
607
609
611
613
633 TriangleMesh &Transform(const core::Tensor &transformation);
634
639 TriangleMesh &Translate(const core::Tensor &translation,
640 bool relative = true);
641
647 TriangleMesh &Scale(double scale, const core::Tensor &center);
648
655 TriangleMesh &Rotate(const core::Tensor &R, const core::Tensor &center);
656
659
662 TriangleMesh &ComputeTriangleNormals(bool normalized = true);
663
666 TriangleMesh &ComputeVertexNormals(bool normalized = true);
667
678 const core::Tensor &normal) const;
679
688 LineSet SlicePlane(const core::Tensor &point,
689 const core::Tensor &normal,
690 const std::vector<double> contour_values = {0.0}) const;
691
692 core::Device GetDevice() const override { return device_; }
693
702 const open3d::geometry::TriangleMesh &mesh_legacy,
703 core::Dtype float_dtype = core::Float32,
704 core::Dtype int_dtype = core::Int64,
705 const core::Device &device = core::Device("CPU:0"));
706
709
724 TriangleMesh ComputeConvexHull(bool joggle_inputs = false) const;
725
739 TriangleMesh SimplifyQuadricDecimation(double target_reduction,
740 bool preserve_volume = true) const;
741
754 double tolerance = 1e-6) const;
755
767 double tolerance = 1e-6) const;
768
780 double tolerance = 1e-6) const;
781
784
787
796 TriangleMesh FillHoles(double hole_size = 1e6) const;
797
828 std::tuple<float, int, int> ComputeUVAtlas(size_t size = 512,
829 float gutter = 1.0f,
830 float max_stretch = 1.f / 6,
831 int parallel_partitions = 1,
832 int nthreads = 0);
833
859 std::unordered_map<std::string, core::Tensor> BakeVertexAttrTextures(
860 int size,
861 const std::unordered_set<std::string> &vertex_attr = {},
862 double margin = 2.,
863 double fill = 0.,
864 bool update_material = true);
865
890 std::unordered_map<std::string, core::Tensor> BakeTriangleAttrTextures(
891 int size,
892 const std::unordered_set<std::string> &triangle_attr = {},
893 double margin = 2.,
894 double fill = 0.,
895 bool update_material = true);
896
905 TriangleMesh ExtrudeRotation(double angle,
906 const core::Tensor &axis,
907 int resolution = 16,
908 double translation = 0.0,
909 bool capping = true) const;
910
917 double scale = 1.0,
918 bool capping = true) const;
919
925 int PCAPartition(int max_faces);
926
932
933protected:
937};
938
939} // namespace geometry
940} // namespace t
941} // namespace open3d
bool copy
Definition VtkUtils.cpp:73
Definition Device.h:18
Definition Dtype.h:20
Definition Tensor.h:32
int64_t GetLength() const
Definition Tensor.h:1114
Tensor Min(const SizeVector &dims, bool keepdim=false) const
Definition Tensor.cpp:1198
Tensor Mean(const SizeVector &dims, bool keepdim=false) const
Definition Tensor.cpp:1177
Tensor Max(const SizeVector &dims, bool keepdim=false) const
Definition Tensor.cpp:1205
Triangle mesh contains vertices and triangles represented by the indices to the vertices.
Definition TriangleMesh.h:35
A bounding box that is aligned along the coordinate axes and defined by the min_bound and max_bound.
Definition BoundingVolume.h:46
Mix-in class for geometry types that can be visualized.
Definition DrawableGeometry.h:19
The base geometry class.
Definition Geometry.h:21
A LineSet contains points and lines joining them and optionally attributes on the points and lines.
Definition LineSet.h:84
A bounding box oriented along an arbitrary frame of reference.
Definition BoundingVolume.h:245
Definition TensorMap.h:31
std::size_t Erase(const std::string key)
Erase elements for the TensorMap by key value, if the key exists. If the key does not exists,...
Definition TensorMap.h:92
bool Contains(const std::string &key) const
Definition TensorMap.h:187
A triangle mesh contains vertices and triangles.
Definition TriangleMesh.h:92
static TriangleMesh CreateText(const std::string &text, double depth=0.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:245
TriangleMesh ExtrudeRotation(double angle, const core::Tensor &axis, int resolution=16, double translation=0.0, bool capping=true) const
Definition TriangleMesh.cpp:969
core::Tensor & GetVertexAttr(const std::string &key)
Definition TriangleMesh.h:136
static TriangleMesh CreateArrow(double cylinder_radius=1.0, double cone_radius=1.5, double cylinder_height=5.0, double cone_height=4.0, int resolution=20, int cylinder_split=4, int cone_split=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:189
TriangleMesh BooleanDifference(const TriangleMesh &mesh, double tolerance=1e-6) const
Definition TriangleMesh.cpp:645
void SetTriangleIndices(const core::Tensor &value)
Set the value of the "indices" attribute in triangle_attr_.
Definition TriangleMesh.h:285
TriangleMesh FillHoles(double hole_size=1e6) const
Definition TriangleMesh.cpp:659
core::Tensor GetMinBound() const
Definition TriangleMesh.h:608
void SetVertexPositions(const core::Tensor &value)
Definition TriangleMesh.h:255
void SetVertexAttr(const std::string &key, const core::Tensor &value)
Definition TriangleMesh.h:248
TriangleMesh & ComputeTriangleNormals(bool normalized=true)
Function to compute triangle normals, usually called before rendering.
Definition TriangleMesh.cpp:213
static TriangleMesh CreateCoordinateFrame(double size=1.0, const Eigen::Vector3d &origin=Eigen::Vector3d(0.0, 0.0, 0.0), core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:210
core::Tensor & GetTriangleNormals()
Definition TriangleMesh.h:172
core::Tensor & GetTriangleAttr(const std::string &key)
Definition TriangleMesh.h:162
void SetVertexColors(const core::Tensor &value)
Definition TriangleMesh.h:262
TensorMap triangle_attr_
Definition TriangleMesh.h:936
void SetTriangleColors(const core::Tensor &value)
Definition TriangleMesh.h:299
TriangleMesh ExtrudeLinear(const core::Tensor &vector, double scale=1.0, bool capping=true) const
Definition TriangleMesh.cpp:979
virtual ~TriangleMesh() override
Definition TriangleMesh.h:110
bool HasTriangleIndices() const
Definition TriangleMesh.h:347
static TriangleMesh CreateBox(double width=1.0, double height=1.0, double depth=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:21
bool HasVertexColors() const
Definition TriangleMesh.h:324
void SetTriangleAttr(const std::string &key, const core::Tensor &value)
Definition TriangleMesh.h:279
core::Device device_
Definition TriangleMesh.h:934
TensorMap & GetVertexAttr()
Getter for vertex_attr_ TensorMap.
Definition TriangleMesh.h:130
TriangleMesh & Clear() override
Clear all data in the trianglemesh.
Definition TriangleMesh.h:599
std::tuple< float, int, int > ComputeUVAtlas(size_t size=512, float gutter=1.0f, float max_stretch=1.f/6, int parallel_partitions=1, int nthreads=0)
Definition TriangleMesh.cpp:673
OrientedBoundingBox GetOrientedBoundingBox() const
Create an oriented bounding box from vertex attribute "positions".
Definition TriangleMesh.cpp:655
void RemoveTriangleAttr(const std::string &key)
Definition TriangleMesh.h:221
TriangleMesh & ComputeVertexNormals(bool normalized=true)
Function to compute vertex normals, usually called before rendering.
Definition TriangleMesh.cpp:249
bool HasTriangleNormals() const
Definition TriangleMesh.h:354
TriangleMesh ComputeConvexHull(bool joggle_inputs=false) const
Definition TriangleMesh.cpp:505
bool HasVertexNormals() const
Definition TriangleMesh.h:331
static geometry::TriangleMesh FromLegacy(const open3d::geometry::TriangleMesh &mesh_legacy, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMesh.cpp:288
void RemoveVertexAttr(const std::string &key)
Definition TriangleMesh.h:189
TriangleMesh To(const core::Device &device, bool copy=false) const
Definition TriangleMesh.cpp:491
open3d::geometry::TriangleMesh ToLegacy() const
Convert to a legacy Open3D TriangleMesh.
Definition TriangleMesh.cpp:373
TensorMap & GetTriangleAttr()
Getter for triangle_attr_ TensorMap.
Definition TriangleMesh.h:156
const core::Tensor & GetTriangleNormals() const
Definition TriangleMesh.h:233
TriangleMesh & NormalizeNormals()
Normalize both triangle normals and vertex normals to length 1.
Definition TriangleMesh.cpp:179
const TensorMap & GetTriangleAttr() const
Getter for triangle_attr_ TensorMap. Used in Pybind.
Definition TriangleMesh.h:153
TriangleMesh Clone() const
Returns copy of the triangle mesh on the same device.
Definition TriangleMesh.h:124
core::Device GetDevice() const override
Returns the device of the geometry.
Definition TriangleMesh.h:692
core::Tensor GetMaxBound() const
Definition TriangleMesh.h:610
TriangleMesh & Rotate(const core::Tensor &R, const core::Tensor &center)
Rotates the VertexPositions, VertexNormals and TriangleNormals (if exists).
Definition TriangleMesh.cpp:164
core::Tensor & GetVertexColors()
Definition TriangleMesh.h:146
TriangleMesh ClipPlane(const core::Tensor &point, const core::Tensor &normal) const
Clip mesh with a plane. This method clips the triangle mesh with the specified plane....
Definition TriangleMesh.cpp:510
static TriangleMesh CreateTorus(double torus_radius=1.0, double tube_radius=0.5, int radial_resolution=30, int tubular_resolution=20, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:171
TriangleMesh SelectFacesByMask(const core::Tensor &mask) const
Definition TriangleMesh.cpp:1002
static TriangleMesh CreateOctahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:111
core::Tensor & GetTriangleIndices()
Definition TriangleMesh.h:168
const core::Tensor & GetTriangleIndices() const
Definition TriangleMesh.h:227
AxisAlignedBoundingBox GetAxisAlignedBoundingBox() const
Create an axis-aligned bounding box from vertex attribute "positions".
Definition TriangleMesh.cpp:651
TriangleMesh BooleanIntersection(const TriangleMesh &mesh, double tolerance=1e-6) const
Definition TriangleMesh.cpp:638
int PCAPartition(int max_faces)
Definition TriangleMesh.cpp:986
const core::Tensor & GetVertexColors() const
Definition TriangleMesh.h:199
TriangleMesh & Scale(double scale, const core::Tensor &center)
Scales the VertexPositions of the TriangleMesh.
Definition TriangleMesh.cpp:153
void SetTriangleNormals(const core::Tensor &value)
Definition TriangleMesh.h:292
core::Tensor & GetVertexPositions()
Definition TriangleMesh.h:142
std::unordered_map< std::string, core::Tensor > BakeTriangleAttrTextures(int size, const std::unordered_set< std::string > &triangle_attr={}, double margin=2., double fill=0., bool update_material=true)
Definition TriangleMesh.cpp:915
bool HasTriangleColors() const
Definition TriangleMesh.h:361
const core::Tensor & GetTriangleColors() const
Definition TriangleMesh.h:239
LineSet SlicePlane(const core::Tensor &point, const core::Tensor &normal, const std::vector< double > contour_values={0.0}) const
Extract contour slices given a plane. This method extracts slices as LineSet from the mesh at specifi...
Definition TriangleMesh.cpp:541
static TriangleMesh CreateMobius(int length_split=70, int width_split=15, int twists=1, double radius=1, double flatness=1, double width=1, double scale=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:224
const core::Tensor & GetVertexPositions() const
Definition TriangleMesh.h:193
bool HasTriangleAttr(const std::string &key) const
Definition TriangleMesh.h:337
static TriangleMesh CreateIcosahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:124
bool HasVertexAttr(const std::string &key) const
Definition TriangleMesh.h:308
const core::Tensor & GetVertexAttr(const std::string &key) const
Definition TriangleMesh.h:181
TriangleMesh & Transform(const core::Tensor &transformation)
Transforms the VertexPositions, VertexNormals and TriangleNormals (if exist) of the TriangleMesh.
Definition TriangleMesh.cpp:124
const TensorMap & GetVertexAttr() const
Getter for vertex_attr_ TensorMap. Used in Pybind.
Definition TriangleMesh.h:127
static TriangleMesh CreateSphere(double radius=1.0, int resolution=20, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:85
void SetVertexNormals(const core::Tensor &value)
Definition TriangleMesh.h:269
const core::Tensor & GetTriangleAttr(const std::string &key) const
Definition TriangleMesh.h:213
core::Tensor GetCenter() const
Definition TriangleMesh.h:612
TensorMap vertex_attr_
Definition TriangleMesh.h:935
core::Tensor & GetTriangleColors()
Definition TriangleMesh.h:176
std::string ToString() const
Text description.
Definition TriangleMesh.cpp:68
core::Tensor & GetVertexNormals()
Definition TriangleMesh.h:150
const core::Tensor & GetVertexNormals() const
Definition TriangleMesh.h:205
bool HasVertexPositions() const
Definition TriangleMesh.h:317
TriangleMesh BooleanUnion(const TriangleMesh &mesh, double tolerance=1e-6) const
Definition TriangleMesh.cpp:632
static TriangleMesh CreateTetrahedron(double radius=1.0, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:98
static TriangleMesh CreateCylinder(double radius=1.0, double height=2.0, int resolution=20, int split=4, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:137
std::unordered_map< std::string, core::Tensor > BakeVertexAttrTextures(int size, const std::unordered_set< std::string > &vertex_attr={}, double margin=2., double fill=0., bool update_material=true)
Definition TriangleMesh.cpp:849
TriangleMesh & Translate(const core::Tensor &translation, bool relative=true)
Translates the VertexPositions of the TriangleMesh.
Definition TriangleMesh.cpp:139
static TriangleMesh CreateCone(double radius=1.0, double height=2.0, int resolution=20, int split=1, core::Dtype float_dtype=core::Float32, core::Dtype int_dtype=core::Int64, const core::Device &device=core::Device("CPU:0"))
Definition TriangleMeshFactory.cpp:154
TriangleMesh SimplifyQuadricDecimation(double target_reduction, bool preserve_volume=true) const
Definition TriangleMesh.cpp:579
bool IsEmpty() const override
Returns !HasVertexPositions(), triangles are ignored.
Definition TriangleMesh.h:606
int width
Definition FilePCD.cpp:52
int size
Definition FilePCD.cpp:40
int height
Definition FilePCD.cpp:53
const Dtype Int64
Definition Dtype.cpp:47
const Dtype Float32
Definition Dtype.cpp:42
constexpr nullopt_t nullopt
Definition Optional.h:152
Definition PinholeCameraIntrinsic.cpp:16