diff --git a/VirtualRobot/Visualization/TriMeshModel.cpp b/VirtualRobot/Visualization/TriMeshModel.cpp
index c692a396d62a68a48982c440e012dab3ec20e08e..1c788b6036d492dcd811a08a08b8d488eb1948b1 100644
--- a/VirtualRobot/Visualization/TriMeshModel.cpp
+++ b/VirtualRobot/Visualization/TriMeshModel.cpp
@@ -620,6 +620,16 @@ namespace VirtualRobot
         return areas;
     }
 
+    float TriMeshModel::getVolume() const
+    {
+        float volume = 0.0f;
+        for (const auto& face : faces)
+        {
+            volume += vertices.at(face.id1).dot(vertices.at(face.id2).cross(vertices.at(face.id3)));
+        }
+        return std::abs(volume);
+    }
+
     void TriMeshModel::rotate(const Eigen::Matrix3f& mx)
     {
         for (auto& vec3f : normals)
diff --git a/VirtualRobot/Visualization/TriMeshModel.h b/VirtualRobot/Visualization/TriMeshModel.h
index 01fa13ceb6cf75ee00e44c1ee72c3f51bc4b60a4..15ae900062fc6a049c631475dda7b23db890ae7f 100644
--- a/VirtualRobot/Visualization/TriMeshModel.h
+++ b/VirtualRobot/Visualization/TriMeshModel.h
@@ -168,6 +168,9 @@ namespace VirtualRobot
         /// Get the areas of all faces.
         std::vector<float> getFaceAreas() const;
 
+        //! Computes the volume of the mesh. Works only for closed meshes
+        float getVolume() const;
+
         void rotate(const Eigen::Matrix3f& mx);
 
         // Overwrite all colors
diff --git a/VirtualRobot/Visualization/TriMeshUtils.cpp b/VirtualRobot/Visualization/TriMeshUtils.cpp
index 35a66a9c4c6e5a251346928c49f272421b942f55..6bc0262c31588d48d63efa800f9cd98094004b1f 100644
--- a/VirtualRobot/Visualization/TriMeshUtils.cpp
+++ b/VirtualRobot/Visualization/TriMeshUtils.cpp
@@ -22,6 +22,9 @@
  *             GNU General Public License
  */
 #include "TriMeshUtils.h"
+#include "../VirtualRobotException.h"
+#include <Eigen/Geometry>
+#include <numeric>
 
 namespace VirtualRobot {
 
@@ -148,4 +151,61 @@ TriMeshModelPtr TriMeshUtils::CreateSparseBoxGrid(const Eigen::Matrix4f &globalP
     return mesh;
 }
 
+
+inline double
+uniformDeviate(int seed)
+{
+  double ran = seed * (1.0 / (RAND_MAX + 1.0));
+  return ran;
+}
+
+Eigen::Vector3f TriMeshUtils::sampleSurfacePoint(std::vector<float> *cumulativeAreas, double totalArea, const TriMeshModel& tri)
+{
+    if (tri.faces.empty())
+    {
+        return Eigen::Vector3f::Zero();
+    }
+
+    float r = static_cast<float>(uniformDeviate(rand()) * totalArea);
+    std::vector<float>::iterator low = std::lower_bound(cumulativeAreas->begin(), cumulativeAreas->end(), r);
+    auto f = tri.faces[low - cumulativeAreas->begin()];
+
+    float r1 = static_cast<float>(uniformDeviate(rand()));
+    float r2 = static_cast<float>(uniformDeviate(rand()));
+
+    float r1sqr = std::sqrt (r1);
+    float OneMinR1Sqr = (1 - r1sqr);
+    float OneMinR2 = (1 - r2);
+    Eigen::Vector3f a = tri.vertices.at(f.id1) * OneMinR1Sqr;
+    Eigen::Vector3f b = tri.vertices.at(f.id2) * OneMinR2;
+    Eigen::Vector3f c = r1sqr * (r2 * tri.vertices.at(f.id3) + b) + a;
+    return c;
+}
+
+std::vector<Eigen::Vector3f> TriMeshUtils::uniformSampling(const TriMeshModel& tri, unsigned int n) {
+    std::vector<Eigen::Vector3f> samples(n);
+
+    std::vector<float> faceAreas = tri.getFaceAreas();
+    std::vector<float> cumulativeAreas(faceAreas.size(), 0.0);
+    float totalArea = 0;
+    for (size_t i = 0; i < faceAreas.size(); i++) {
+        totalArea += faceAreas[i];
+        cumulativeAreas[i] = totalArea;
+    }
+
+    unsigned int i = 0;
+    unsigned int counter = 0;
+    while (i < n) {
+        Eigen::Vector3f sampledPoint = sampleSurfacePoint(&cumulativeAreas, totalArea, tri);
+        if (!sampledPoint.isZero()) {
+            samples[i] = sampledPoint;
+            i++;
+            counter = 0;
+        }
+        if (counter > 10)
+            throw VirtualRobotException("Sampling surface points gone wrong!");
+    }
+    return samples;
+}
+
 } // namespace VirtualRobot
diff --git a/VirtualRobot/Visualization/TriMeshUtils.h b/VirtualRobot/Visualization/TriMeshUtils.h
index cc28fe82661508a66fdba651832a07ec120a8089..8dfbb89095d6b30bc40158bb6631fdb85795634c 100644
--- a/VirtualRobot/Visualization/TriMeshUtils.h
+++ b/VirtualRobot/Visualization/TriMeshUtils.h
@@ -39,6 +39,9 @@ public:
                                                const VisualizationFactory::Color &color = VisualizationFactory::Color::Gray(),
                                                const std::vector<VisualizationFactory::Color>& colors = {});
 
+    static Eigen::Vector3f sampleSurfacePoint(std::vector<float> *cumulativeAreas, double totalArea, const VirtualRobot::TriMeshModel& tri);
+    //! Uniformly samples points on the surface of a trimesh model and can be used to create a point cloud of the model
+    static std::vector<Eigen::Vector3f> uniformSampling(const VirtualRobot::TriMeshModel& tri, unsigned int n = 1000);
 };
 
 } // namespace VirtualRobot