Code Monkey home page Code Monkey logo

meshlib's Introduction

Open in Gitpod

build-test-distribute PyPI version Python Downloads

MeshInspector/MeshLib

Welcome to the MeshLib!

3D scanning is becoming more and more ubiquitous. Robotic automation, self-driving cars and multitude of other industrial, medical and scientific applications require advanced computer vision to deliver the levels of automation customers expect these days. The great rise of AI gave another boost to computer vision and the need to utilize 3D data to make machines smarter. Not only are tasks at hand becoming more complex, but the size of data grows exponentially.

There is a multitude of general purpose libraries which deal with 3D data. Some stem from popular CAD packages, some are open source. The commercial ones tend to be quite expensive while open source are free though tend to be limited in functionality provided. Also those libraries value generality above other features to allow maximum number of applications, but with the growing amounts of 3D data, performance is critical as it never has been. Some of it can be addressed by using the scale of a commercial cloud, last generation CPU or GPU but underlying complexity of data representation makes it very hard and laborsome.

The goal which we set when designing MeshLib was to value simplicity and performance while providing a wide gamut of useful computational algorithms. The library also supports the most important data structures today’s sensors can produce - pointcloud, mesh, volume and more. For example, mesh is represented by half-edge data structure and cannot be made non-manifold. Some applications may require non-manifoldness, but most practical scans can be represented as manifoldness meshes without an issue.

Some useful links

Major features

This list is not full and updating each day

Math basics

  • Math primitives and operations support (Vectors 2D, 3D, 4D; Lines; Planes; Bounding Boxes; Matrices; Affine transformations; Quaternions; Histograms; etc.)

3D data handling, creation, modification

  • 3D data various representations support: Mesh, Voxel and Point Cloud.
  • Data creation
    • Mesh creation by given vertices and triangles,
    • Surface primitives (e.g. tor, cube, sphere, etc).
  • Representation conversions
    • Triangulation of a Point Cloud to Mesh,
    • Mesh to Cloud Point conversion,
    • Mesh to Voxel conversion,
    • Voxel To Mesh conversion.
  • Deformations
    • Laplassian deformation,
    • Freeform deformation,
    • Relax, mesh smoothing,
    • Position Verts Smoothly, arrangement of vertices in accordance with the gradient along the neighbors.
  • Offsets
    • Mesh offset,
    • Mesh partial offset.
  • Resolution
    • Breaking a mesh into smaller triangles (increasing the resolution)
    • Mesh decimation (decreasing the number of triangles, decreasing the resolution) with a specified error relative to the old mesh.
  • Cutting a contour on a surface. The mesh is modified so that the resulting contour contains new edges cut through triangles at the specified points.
  • Splitting
    • Splitting mesh into sub-meshes (components)

3D data operations

  • Boolean operations (union, intersection, difference) on 3D objects bounded by meshes. MeshLib has two independent modes:
    1. Boolean ops on meshes via intermediate conversion into voxel representation. This mode requires closed meshes without holes on input and much memory for high accuracy but tolerate for various input mesh degenerations and self-intersections.
    2. Direct Boolean ops on meshes using robust predicates, producing exact accurate result and keeping original mesh elements as is if they are not intersected. This mode supports for open meshes with holes as long as the boundary of the mesh is not intersected.
      • According to our user reports, MeshLib direct Boolean operations are significatly faster even compared to the latest published approaches, e.g. Interactive and Robust Mesh Booleans
  • Construction of Convex Hull of a point cloud or a mesh.

3D Data problems fixing

  • Fixing holes in mesh
    • Holes stitching (removing two holes by stitching their boundaries)
    • Hole filling,
    • Holes fixing metrics
      • Basic set of triangulation metrics,
      • Extended set of triangulation metrics,
      • Custom triangulation metrics.
  • Delaunay triangulation optimization, changing triangles without changing vertices, according to Delaunay criterion,
  • Tunnels fixing,
  • Multiple edges detection
  • Degenerate triangles fixing,
  • Undercuts fixing, via voxels,
  • Surface self-intersections fixing
    • Guaranteed fix via voxels,
    • Fix via Relax (mesh smoothing).

Functions on 3D data

  • BVH hierarchies (AABB trees) for meshes and polylines to accelerate all other operations
  • Projection
    • Projecting a point onto a mesh - closest point queries
  • Intersection
    • Intersection of a ray with a mesh (ray tracing),
    • Intersection of a plane with a mesh, result is a contour,
    • Finding a contour representing intersection of two meshes, meshes remain unchanged,
  • Distance
    • Distance from a point to a mesh,
    • Minimal distance between two meshes,
    • Mesh distance map (height map),
    • 2D contour distance map.
  • Segmentation
    • Semi-auto voxel segmentation (volumes classification).
    • Semi-auto mesh segmentation by curvature.
  • Sampling
    • Mesh sampling. The result is a separate thinned set of vertices, the mesh remains unchanged.
    • Point cloud sampling. The result is a separate thinned set of points, the cloud remains unchanged
      • Uniform cloud sampling,
      • Grid cloud sampling.
  • Path
    • Finding a shortest path through the mesh vertices,
    • Finding a geodesic shortest path on the surface, not necessarily through mesh vertices.
  • Iterative Closest Points (ICP), two meshes aligning
    • Point to point,
    • Point to plane.

Upcoming features

We plan to add computed-tomography reconstruction in MeshLib (already present in MeshInspector). Please write us if you like to see some other features.

Python integration

Although MeshLib is written in C++, all functions are exposed to Python as well. Python code can be executed both from within a MeshLib-based C++ application (embedded mode) and from python interpreter directly, which imports MeshLib modules.

Moreover, the latest MeshLib released version can be easily installed as a Python 3.8 - 3.12 package using pip install:

  • On Windows via
py -3 -m pip install --upgrade pip
py -3 -m pip install --upgrade meshlib
  • On Linuxes supporting manylinux_2_31+, including Ubuntu 20+ and Fedora 32+ via
sudo apt install python3-pip
python3 -m pip install --upgrade pip
python3 -m pip install --upgrade meshlib
  • On macOS 12.0+ via
pip install --upgrade pip
pip install --upgrade meshlib

See Python Basic Examples here or search for more complex ones on stackoverflow.com.

Build

Windows

MeshLib can be build on Windows using either Visual Studio 2019 or Visual Studio 2022, both of which support c++20 language standard.

git clone https://github.com/MeshInspector/MeshLib.git
cd MeshLib
git submodule update --init --recursive
cd ..

Note: following below steps will take about 40Gb of your disk space.

Preparing Third Parties

Some third parties are taken from vcpkg, while others (missing in vcpkg) are configured as git submodules.

CUDA

Windows version of MeshLib is configured to use

  • CUDA v11.4 in Visual Studio 2019 and
  • CUDA v12.0 in Visual Studio 2022.

Please install CUDA from the official site. If you would like to use another version of CUDA, please modify MRCudaVersion in MeshLib/source/platform.props.

Vcpkg

  1. Please install vcpkg, and integrate it into Visual Studio (note that vcpkg requires English language pack in Visual Studio, and vcpkg cannot be installed on FAT volumes, only on NTFS):

    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    git checkout 2024.03.25
    .\bootstrap-vcpkg.bat
    .\vcpkg integrate install (with admin rights)

    More details here: vcpkg.

  2. (Optional, but recommended) Install AWS CLI v2. Once installed, reopen PowerShell or CMD. This will allow you to use the vcpkg binary cache from our aws s3, which will speed up the installation process and reduce the required disk space.

  3. Execute MeshLib/thirdparty/install.bat having previously installed vcpkg as the current working directory (or simply add vcpkg to PATH environment variable).

  4. Open solution file MeshLib/source/MeshLib.sln in Visual Studio. Build it and run.

Linux

We regularly check that MeshLib can be built successfully on Ubuntu 20.04 LTS, Ubuntu 22.04 LTS (both x64 and ARM), and Fedora 37.

Install/Build dependencies. Build project. Run Test Application

Install CUDA v12.0 from official site

Use automated installation process. It takes ~40 minutes if no required packages are already installed. This approach is useful for new MR developers

Run the following in terminal:

git clone --recurse-submodules https://github.com/MeshInspector/MeshLib.git
cd MeshLib
./scripts/build_thirdparty.sh  # do not select emscripten in the corresponding question
./scripts/build_source.sh  # do not select emscripten in the corresponding question
# create and install package for Ubuntu
./scripts/distribution.sh
sudo apt install ./distr/meshlib-dev.deb
# create and install package for Fedora
./scripts/distribution_rpm.sh
sudo apt install ./distr/meshlib-dev.rpm

NOTE: ./scripts/install*.sh scripts could be used as well, but apt install is preferable.

NOTE: ./scripts/install_thirdparty.sh script copies MR files directly to /usr/local/lib. Remove this directory manually if exists before apt install deb package.

NOTE: You could specify build type to Debug by export MESHLIB_BUILD_TYPE=Debug. Release is default. Set MESHLIB_KEEP_BUILD=ON to suppress full rebuild

WASM/Emscripten

This installation was checked on Ubuntu 22.04 with Emscripten 3.1.48.

Install Emscripten (find more on Emscripten official page)

git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
git pull origin # optional
./emsdk install 3.1.48 # (or another version / latest)
./emsdk activate 3.1.48
source ./emsdk_env.sh

Build

cd ~/MeshLib
./scripts/build_thirdparty.sh # select Emscripten in the corresponding question
./scripts/build_source.sh # select Emscripten in the corresponding question

NOTE: Set MESHLIB_KEEP_BUILD=ON to suppress full rebuild

Run

python3 -m http.server 8000 # note that server should have specific COEP and COOP policies for multithread version
# open in browser 127.0.0.1:8000

Integration

Linux Ubuntu/Fedora

You can download dev package and install it with your Linux OS package manager. Examples of integration with cmake can be found in the ./examples directory.

MacOS

Same as for Linux, but requires brew packages to be installed:

xargs brew install < /Library/Frameworks/MeshLib.framework/Versions/Current/scripts/macos.txt

Windows

There are two general options of integrating MeshLib into your project:

  1. Submodule
  2. Distribution

Common for both options: install thirdparty

Submodule

You can have MeshLib as submodule in your repository, and inculde all MeshLib's projects to your solution.

NOTE: You should use MeshLib/source/common.props in other projects of your solution.

NOTE: You can customize props by defining CustomMRProps.props in directory above common.props

Distribution

You can download distribution and integrate it in your projects.

Project settings:

  1. C/C++ -> General -> Additional Include Directories add distribution\install\include;
  2. Linker -> General -> Additional Library Directories add distribution\install\app\$(Configuration);
  3. Linker -> Input -> Additional Dependencies add distribution\install\lib\$(Configuration)\*.lib;
  4. Debug: C/C++ -> Preprocessor -> Preprocessor Defenitions add _ITERATOR_DEBUG_LEVEL=0;
  5. vcpkg -> Triplet set x64-windows-meshlib

Make sure you copy all dlls from distribution\install\app\$(Configuration); to your $(TargetDir)

NOTE: MeshLib distribution has x64 build only

NOTE: Distribution is build with ITERATOR_DEBUG_LEVEL=0 in debug so you will need to setup this for your projects

meshlib's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meshlib's Issues

Interactive Contour Labels

This one is a long shot and not directly related to MeshLib so please bear with me while I explain. In my application, I rely on a GLSL shader to draw contour lines interactively. The majority of the logic takes place in the Geometry Shader, which essentially implements this algorithm.

It works very fast even for complex meshes and I'm happily sharing the code below if you wanted to incorporate it into the MeshInspector.

2023-07-18.16-17-50.mp4

Things slow down, however, when I start displaying labels. The GLSL shader, is only aware of one primitive (triangle) at a time and generates unconnected line segments. I couldn't figure out a way of joining these segments on the GPU, hence I copy them over to the CPU and sort them there. It gets me the results I want, but leads to noticeable slow downs with more complex meshes.

Do you have any suggestions on how to approach it in a more efficient way?

The GLSL shader code:

//vertexShader 
#version 330
layout(location = 0) in vec3 _meshVertex;
layout(location = 1) in vec3 _meshNormal;

out vec3 _normal;

void main() {
_normal = vec3(_meshNormal * 0.01); // offset contours by a small amount to prevent Z-fighting
gl_Position = vec4(_meshVertex + _normal, 1.0);
}

// geometryShader
#version 330 core
layout (triangles) in;
layout (line_strip, max_vertices = 64) out;

uniform mat4 _worldToClip;
uniform vec4 minorColor;
uniform vec4 majorColor;

uniform float majorInterval;
uniform float interval;
uniform int multiplier = 100; // used for float precision while searching for major contours

in vec3 _normal[];
out vec4 color;
out vec3 _positionT;
out vec3 _normalT;


int countAB;
int countBC;
int countCA;

float interpolate(float start, float end, float t){
    return start + t * (end - start);
}
vec3[100] computeIntersections(vec4 start, vec4 end, inout int counter){

    vec3[100] points;
    counter = 0;
    
    float minValue = min(start.z, end.z);
    float maxValue = max(start.z, end.z);
    float startValue = minValue - mod(minValue, interval);
    float delta = maxValue - minValue;
    float nLevels = floor((maxValue - startValue) / interval);

    for(int i = 0; i <= nLevels; i++){
        float value = startValue + (i * interval);
        if (value < minValue || value > maxValue)
            continue;
        float ratio = (value - minValue) / delta;
        if(start.z > end.z) ratio = 1 - ratio;
        vec3 point = vec3(interpolate(start.x, end.x, ratio), interpolate(start.y, end.y, ratio), value);
        points[counter] = point;
        counter++;
    }
    return points;
}
void drawContours(vec3 normalVector, vec3[100] start, vec3[100] end, vec3[100] mid, int startCount, int endCount, int midCount) {
         _normalT = normalVector;

    for (int i = 0; i < 35; i++) {
         if (i >= startCount) break;
         color = mod(round(start[i].z * multiplier), round(majorInterval * multiplier)) != 0 ? minorColor : majorColor;

         _positionT = vec3(start[i].x, start[i].y, start[i].z);
         gl_Position = _worldToClip * vec4(start[i], 1.0);
         EmitVertex();
         _positionT = vec3(end[i].x, end[i].y, end[i].z);
         gl_Position = _worldToClip * vec4(end[i], 1.0);
         EmitVertex();
         EndPrimitive();
     }

     int count = endCount - startCount;
     for (int i = 0; i < 15; i++) {
         if (i >= count) break;
         color = mod(round(end[endCount - 1 - i].z * multiplier), round(majorInterval * multiplier)) != 0 ? minorColor : majorColor;
         _positionT = vec3(end[endCount - 1 - i].x, end[endCount - 1 - i].y, end[endCount - 1 - i].z);
         gl_Position = _worldToClip * vec4(end[endCount - 1 - i], 1.0);
         EmitVertex();
         _positionT = vec3(mid[midCount - 1 - i].x, mid[midCount - 1 - i].y, mid[midCount - 1 - i].z);
         gl_Position = _worldToClip * vec4(mid[midCount - 1 - i], 1.0);
         EmitVertex();
         EndPrimitive();
     }
}
void main() {    
     int counter1;
     int counter2;
     
     vec3[] AB = computeIntersections(gl_in[0].gl_Position, gl_in[1].gl_Position, countAB);
     vec3[] BC = computeIntersections(gl_in[1].gl_Position, gl_in[2].gl_Position, countBC);
     vec3[] CA = computeIntersections(gl_in[2].gl_Position, gl_in[0].gl_Position, countCA);
     
     // A is the lowest point
     if (gl_in[0].gl_Position.z < gl_in[1].gl_Position.z && gl_in[0].gl_Position.z < gl_in[2].gl_Position.z)
     {
         if(countAB < countCA)
            drawContours(_normal[0], AB, CA, BC, countAB, countCA, countBC);
         else
            drawContours(_normal[0], CA, AB, BC, countCA, countAB, countBC);
     } 
     
     // A is the highest point
     else if (gl_in[0].gl_Position.z > gl_in[1].gl_Position.z && gl_in[0].gl_Position.z > gl_in[2].gl_Position.z)
     {
         if(countAB < countCA)
            drawContours(_normal[0], BC, CA, AB, countBC, countCA, countAB);
         else
            drawContours(_normal[0], BC, AB, CA, countBC, countAB, countCA);
     } 
     
     // B lowest & C highest
     else if (gl_in[2].gl_Position.z > gl_in[0].gl_Position.z && gl_in[0].gl_Position.z > gl_in[1].gl_Position.z)
     {
        drawContours(_normal[0], AB, BC, CA, countAB, countBC, countCA);
     }
     // C lowest & B highest
     else
     {
         drawContours(_normal[0], CA, BC, AB, countCA, countBC, countAB);
     }

} 

//fragmentShader
#version 330 core
out vec4 FragColor;
in vec4 color;

void main()
{
  FragColor = color;
}  

The c# code taking an array of float containing vertex coordinates and normal vectors of respective start & end points of each line segment. Here is the layout, where V1 is a vertex, and N1 its corresponding normal vector.

contourPoints = [V1x, V1y, V1z, N1x, N1y, N1z, V2x, V2y, ... ];
        public void UpdateContourLabels()
        {
            var labels = new Dictionary<double, (List<Point3d>, List<Vector3d>)>();

            if (WorkingMesh == null) return;

            int correctForQuadFaces = WorkingMesh.Faces.QuadCount > 10 ? 2 : 1;
            int count = 0;
            if (generatedPointsCount != null)
                count = (int)generatedPointsCount[0] * 6 * correctForQuadFaces;

            for (int i = 0; i < count; i += 6) // Stride is 6 due to two vec3 coming from the geometry shader
            {
                Point3d p = new Point3d
                {
                    X = contourPoints[i],
                    Y = contourPoints[i + 1],
                    Z = Math.Round(contourPoints[i + 2], 2)
                };

                if (!labels.ContainsKey(p.Z))
                {
                    var v = new Vector3d
                    {
                        X = contourPoints[i + 3],
                        Y = contourPoints[i + 4],
                        Z = contourPoints[i + 5]
                    };

                    labels.Add(p.Z, (new List<Point3d> { p }, new List<Vector3d> { v }));
                }
                else
                {
                    bool isClose = false;
                    foreach (var point in labels[p.Z].Item1)
                    {
                        if (point.DistanceToSquared(p) < TerrainData.ContourLabelSpacing.CurrentValue)
                        {
                            isClose = true;
                            break;
                        }
                    }
                    if (!isClose)
                    {
                        var v = new Vector3d
                        {
                            X = contourPoints[i + 3],
                            Y = contourPoints[i + 4],
                            Z = contourPoints[i + 5]
                        };

                        labels[p.Z].Item1.Add(p);
                        labels[p.Z].Item2.Add(v);
                    }
                }
            }
            ContourLabels = labels;
        }

Unstable Boolean Operations

Hey MeshLib Team,

I've been experimenting with various boolean operations and have encountered some inconsistencies with specific kinds of geometry.

Note how this configuration works:
image

But moving the cylinder to the sides results in an invalid mesh:
image
image

Code is super simple:

BooleanResult res = boolean( *meshA, *meshB, BooleanOperation::DifferenceAB );

And here is a preview of the results in a debug session where it's clear that the above function returns an empty mesh:
image

I'm attaching the geometry in a position which doesn't work on my machine:
Boolean.zip

[EDIT] I'm running the master branch with this snapshot:
image

MeshInspector app cannot run on iphone 8 (ios 14.5)

Hello,

The meshlib demo web application(https://app.meshinspector.com/RMISingle/) cannot run on iphone8 (ios 14.5). I tested it on real machine and the simulator, both failed. Besides, it runs normally with higher ios version.

I compiled the web application(single-thread) from source code, but result in same problem.

It will be much helpful if the single-thread (and maybe no simd?) meshlib can work on much more mobile deivces. Do you have any ideas? Thanks.

Find boundary intersections

Hello,If I know two points on the model surface, can I use those two points to find the intersection with the model boundary?
a1e793910649c1d212d69d2266fb6bf


We can use the following as input: mesh, upper surface, two point coordinates.
Desired result: Find the intersection with the left boundary

Building on Windows

I'm trying to build MeshLib on Windows 10 following this guide.

It fails at the following line:
../MeshLib/thirdparty/install.bat

set VCPKG_DEFAULT_TRIPLET=x64-windows-meshlib

error: Invalid triplet: x64-windows-meshlib
Available architecture triplets:
vcpkg built-in triplets:
  arm-uwp
  arm64-windows
  x64-linux
  x64-osx
  x64-uwp
  x64-windows-static
  x64-windows
  x86-windows
VCPKG community triplets:
  arm-android
  arm-ios
  arm-linux
  arm-mingw-dynamic
  arm-mingw-static
  arm-neon-android
  arm-windows-static
  arm-windows
  arm64-android
  arm64-ios
  arm64-linux
  arm64-mingw-dynamic
  arm64-mingw-static
  arm64-osx-dynamic
  arm64-osx
  arm64-uwp
  arm64-windows-static-md
  arm64-windows-static
  armv6-android
  ppc64le-linux
  s390x-linux
  wasm32-emscripten
  x64-android
  x64-freebsd
  x64-ios
  x64-linux-dynamic
  x64-linux-release
  x64-mingw-dynamic
  x64-mingw-static
  x64-openbsd
  x64-osx-dynamic
  x64-osx-release
  x64-windows-release
  x64-windows-static-md
  x86-android
  x86-freebsd
  x86-ios
  x86-mingw-dynamic
  x86-mingw-static
  x86-uwp
  x86-windows-static-md
  x86-windows-static
  x86-windows-v120

I replaced the triplet with x64-windows-release and it proceeded further but fails at installing boost:

error: building boost-system:x64-windows-release failed with: BUILD_FAILED
error: Please ensure you're using the latest port files with `git pull` and `vcpkg update`.
Then check for known issues at:
    https://github.com/microsoft/vcpkg/issues?q=is%3Aissue+is%3Aopen+in%3Atitle+boost-system
You can submit a new issue at:
    https://github.com/microsoft/vcpkg/issues/new?template=report-package-build-failure.md&title=[boost-system]+Build+error
Include '[boost-system] Build error' in your bug report title, the following version information in your bug description, and attach any relevant failure logs from above.
    vcpkg-tool version: 2022-11-10-5fdee72bc1fceca198fb1ab7589837206a8b81ba
    vcpkg-scripts version: 6f7ffeb18 2022-11-11 (7 months ago)

Is this a known issue?

Find the half edge between two points

If I input two coordinate points of the surface model, I want to find the half of the geodesic distance between the two points?
d7fb11e287f30604bf17f53a314b08d
How should I split the mesh and figure out the proper half edge?
code**************************
auto cylinder = MR::MeshLoad::fromAnyStl("D:/code/meshlib221/chamfer/model/cylinder.stl");
MR::vector3f pointA;
MR::vector3f pointB;
code****************************
Do I need to split the mesh one by one?
std::vectorMR::EdgeId MeshContours;

Two contour fills

I see that the software currently only supports one contour for filling.
image
I can't choose two contours
If I want to fill between two contours, how should I do it best?I need to fill between two contours

mrmeshpy.boolean intersection returns not(intersection)

I am trying to calculate the intersection between two meshes by calling

import meshlib.mrmeshpy as mr
mesh_a = ...
mesh_b = ...
diff = mr.boolean(mesh_a, mesh_b, mr.BooleanOperation.Intersection)

However, instead of returning the intersection of the two meshes, I end up getting the not(intersection) of the two meshes. By not(intersection) i mean parts of mesh_a that don't lie inside mesh_b.

For example, given mesh_a:

with mesh_b on top:

i get the intersection as:

Any clue on what might be happpening?

Part of the feature edge

I found that there is a global search for feature edges in the software.But if I want to find a local segment of a line.What should I do better?
For example, the cyan edge has two tangent lines at both ends.
27f4d1b5896df1b3fc39f1d30a05b49
How should I find out the local characteristic edge out

Find the coordinates of a vertex

Hello,Does it currently support finding coordinates by point index value?I found that the point coordinates are found through the half-edge structure.
code*******
MR::Vector3f orgpoint = cylinder->orgPnt(edge);


If I have a vertex id, can I directly retrieve its coordinates?
For example:MR::VertId Id;Can I find it directly through this id?
Thanks a lot

Python, 'region' attribute error when subdivide mesh: 'meshlib.mrmeshpy.SubdivideSettings' object has no attribute 'region'

Hello everyone,

There is an attribute error when i want to subdivide a region of mesh and set the 'region' attribute. Below is my test code, its the test code from MeshLib/test_python/test_subdivider.py but with 'region' attribute modifed. And I have not figure out how to set the 'region' attribute value rightly, so just set as None to show the error.

from helper import *
import pytest


def test_subdivider():
    torus = mrmesh.makeTorus(2, 1, 10, 10, None)
    countInit = torus.topology.getValidFaces().count()

    settings = mrmesh.SubdivideSettings()
    settings.maxEdgeLen = 0.3
    settings.maxEdgeSplits = 5
    settings.maxDeviationAfterFlip = 0.2

    # Error: 'meshlib.mrmeshpy.SubdivideSettings' object has no attribute 'region'
    settings.region = None

    mrmesh.subdivideMesh(torus, settings)

    assert (torus.topology.getValidFaces().count() > countInit)

The error says,

'meshlib.mrmeshpy.SubdivideSettings' object has no attribute 'region'

Besides, I found the 'region' attribute is indeed binded and there also exists 'region' attribute in debug window, but i still cannot set this attribute and the error occured.

the debug window picture,
Screenshot from 2022-12-08 12-34-14

Finally, thank you for this amazing library!

Find the index of the triangle face

Hello,Is it possible to add index information of triangular faces to this software?When I use this software, I want to quickly find the index value or coordinates of a certain vertex, or the index value of a certain patch through the visual interface.

MROffset to keep sharp features

you use openvdb to do mesh offset. It is good. but the origin openvdb code can not preserve sharp features.
Do you have plans to optimize the code to keep sharp features?

pip install failing

when I try pip install meshlib I get this error

ERROR: Could not find a version that satisfies the requirement meshlib (from versions: none)
ERROR: No matching distribution found for meshlib

I've tried on a variety of different python versions on mac and linux and the error persists.

MeshLib using

Hi,are there some examples can use to learn how to use the api?

CutMesh with world contour and extracting cuted parts

If I input ordered points(The points are not in the same plane), first I want to project the points onto the surface of the model, secondly cut the grid model through the connection between points, and finally I want to fill the cut surface with a new surface.
1.I need to intercept this contour line on the model
2.I need to cutmesh by this contour(The contour points are not in the same plane)

Inconsistency issue after reading mesh with fromAnySupportedFormat function.

Thank you for providing such an excellent library. However, I have encountered the following issue while using it. As indicated in the comments in the main function, I provided verts and faces to generate the mesh and saved the mesh locally. However, upon reloading the mesh, I noticed that the lengths of the read verts and faces no longer match the original ones. What could be the reason for this?

#include <iostream>
#include <vector>
#include "MRMesh/MRMesh.h"
#include "MRMesh/MRMeshLoad.h"
#include "MRMesh/MRMeshSave.h"
#include "MRMesh/MRPointCloud.h"
#include "MRMesh/MRMeshBuilder.h"


template <typename T>
std::vector<std::array<T, 3>> array1dTo2d(const T* data, const int dataLength) {
    std::vector<std::array<T, 3>> ret;
    for (int i = 0; i < dataLength; i += 3) {
        std::array<T, 3> vs{data[i], data[i + 1], data[i + 2]};
        ret.push_back(vs);
    }
    return ret;
}


void printVerts(const MR::Mesh& mesh)
{
    int numVerts = mesh.topology.lastValidVert() + 1;
    std::vector<float> datas;
    datas.reserve(numVerts * 3);

    for (int i=0; i< numVerts; i++)
        for (int j=0; j<3; j++)
            datas.push_back(mesh.points.vec_[i][j]);

    for (const float& value : datas) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
}

void printFaces(const MR::Mesh& mesh)
{
    const auto& validFaces = mesh.topology.getValidFaces();
    int numFaces = mesh.topology.lastValidFace() + 1;
    std::vector<int> datas;
    datas.reserve(numFaces * 3);

    for ( int i = 0; i < numFaces; ++i )
    {
        MR::FaceId f = MR::FaceId( i );
        if ( validFaces.test( f ) )
        {
            MR::VertId v[3];
            mesh.topology.getTriVerts( f, v );
            for ( int vi = 0; vi < 3; ++vi )
                datas.push_back(v[vi]);
        }
        else
        {
            for ( int vi = 0; vi < 3; ++vi )
                datas.push_back(0);
        }
    }
    for (const int& value : datas) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
}


MR::Mesh transToMesh(const float* verts1d, const int verts1dLength, const int* faces1d, const int faces1dLength)
{
    std::vector<std::array<float, 3>> verts2d = array1dTo2d(verts1d, verts1dLength);
    std::vector<std::array<int, 3>> faces2d = array1dTo2d(faces1d, faces1dLength);

    MR::Triangulation t;
    MR::Mesh result;
    t.reserve(faces2d.size());

    for (const std::array<int, 3>& data : faces2d) {
        t.push_back( {
            MR::VertId( int( data[0] ) ),
            MR::VertId( int( data[1] ) ),
            MR::VertId( int( data[2] ) )
            } );
    }

    result.topology = MR::MeshBuilder::fromTriangles( t );
    result.points.resize(verts2d.size());
    for (int i=0; i<faces2d.size(); i++){
        result.points[MR::VertId( i )] = MR::Vector3f(
                float( faces2d[i][0] ),
                float( faces2d[i][1] ),
                float( faces2d[i][2] ) );
    }
    return result;
}

int main() {
    float verts[] = {0.0, 1.0, 2.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    int faces[] = {0, 1, 2, 2, 3, 0};

    MR::Mesh mesh = transToMesh(verts, 12, faces, 6);
    // In the generated mesh using the provided verts and faces, 
    // the read verts and faces match the given ones.
    printVerts(mesh);   //    The output print is as follows:  0 1 2 2 3 0 0 0 0 0 0 0
    printFaces(mesh);   //   The output print is as follows:  0 1 2 2 3 0
    MR::MeshSave::toAnySupportedFormat( mesh, "output.stl" );

    MR::Mesh outputMesh = MR::MeshLoad::fromAnySupportedFormat("output.stl").value();
    // When I save the previous mesh to the local storage and then reload it, 
    // the read verts and faces do not match the provided ones.
    printVerts(outputMesh);   //  The output print is as follows:  0 1 2 2 3 0 0 0 0
    printFaces(outputMesh);   //  The output print is as follows:  0 1 2

    return 0;
}

Inspect > Distance Compare map between two meshes in python?

Hi,
Great work! But I feel the documentation is lagging behind the efforts. I wanted to know if it is possible to use the "Inspect > Distance Compare" functionality of Mesh Inspector, but completely in python? For example, I could compute the Signed Distance between the two meshes using:

  import meshlib.mrmeshpy as mr

  mesh1 = mr.loadMesh("Cube.stl")
  mesh2 = mr.loadMesh("Torus.stl"))
  z = mr.findSignedDistance(mesh1, mesh2)
  print(z.signedDist)

Which gives the same output as "Inspect > Signed Distance" in Mesh Inspector.
How to have the Distance Compare map in python?

Thank you.

Mesh Traversal

I'm trying to gain a better understanding of how to navigate the mesh topology. Could you please point me in the right direction when it comes to the following operations?

  1. Face/Edge/Vertex Selection
    Given a ray, how can I select the intersecting mesh element? The function below returns a MeshTriPoint, is there a way to retrieve the corresponding Face, Edge or Vertex?

    MRMESH_API std::optional<MeshIntersectionResult> rayMeshIntersect( const MeshPart& meshPart, const Line3f& line,
    float rayStart = 0.0f, float rayEnd = FLT_MAX, const IntersectionPrecomputes<float>* prec = nullptr, bool closestIntersect = true );

  2. Internal Face Selection
    Given a closed edge loop (cyan), select all internal faces (yellow):
    image
    image

  3. Hole & Boundary Selection
    Given a single edge (cyan), select the entire edge loop forming the hole boundary (yellow). Same applies to external boundaries:
    image
    image

  4. Expanding/Shrinking Selection
    Given an arbitrary amount of selected faces expand or shrink the selection to include the neighboring faces:
    image
    image

How to split mesh with a new point?

Hi, thanks to such a powerful library for 3d process.

Could anyone please help me with an easy case here: How to split mesh with a new point?

For example:
CU%97 (GH(@W6`KBRCZCJHJ

I have read all documents from meshlib, but examples useful for my case cannot be found.
Because I am familiar with python but not with C++, I have difficults to understand all the function details from documents.

Thank you very much if anyone can help!

Cut meshes with polylines

First of all - thanks for your great work on this library! It's really coming together nicely!

Since there is no dedicated Discussion section, I'd like to ask here whether it's possible to cut meshes with polylines. Example below:

image

Please note how new vertices and edges are introduced to the mesh and it is pulled towards the user provided polyline.
Any suggestions how this could be achieved in MeshLib?

Support >1 textures

It would be nice to support >1 textures per object.

The max number of textures could be an initialization param of TPViewer (even better if it could be changed at runtime). Making the parameter a #define would be slighty unconvenient.

Each vertex would have N different texture coords, one per texture. Textures would be mixed according to their alpha channel.

Geodesic Question

Hello,Is it not possible to use the output results directly?
When I use the geodesic algorithm directly, I find that the points in the middle cannot be printed
code**********
auto model = MR::MeshLoad::fromAnyStl("D:/code/meshlib223/ChamferAllEdges/model/Subtraction.stl");
auto firstTriPointTest = MR::MeshTriPoint::MeshTriPoint(model->topology, model->topology.org(MR::EdgeId(211)));
auto secondTriPointTest = MR::MeshTriPoint::MeshTriPoint(model->topology, model->topology.org(MR::EdgeId(111)));
MR::GeodesicPathApprox atype = MR::GeodesicPathApprox::DijkstraBiDir;
auto geoDesicPath = MR::computeGeodesicPathApprox(model,firstTriPointTest,secondTriPointTest,atype);
for (auto geoDesic : geoDesicPath)
{
std::cout << model->edgePoint(geoDesic).x << " " << model->edgePoint(geoDesic).y << " " << model->edgePoint(geoDesic).z << std::endl;;
}
code
************

mesh denoising that can keep sharp features

Do you have plans to write mesh denoising algorithms that can keep sharp features of flat regions and smooth regions.
image
see the flat regions and the hole in the above image

Fill part of the face

If I have a contour surface,I want to fill one part first and then fill another part. I can split contours into two parts.
eec7b0282434c21510b989d4fcef18d
How should I avoid the influence of patch modification after the first filling?

Remeshing

Encouraged by the performance of mesh booleans and polyline-mesh intersections, I took the remeshing function for a spin:

MRMESH_API bool remesh( Mesh& mesh, const RemeshSettings & settings );

Below is a comparison with Geometry Central and cinolib

2023-06-17.19-49-08.mp4

In the upper left corner you see the timings and MeshLib is a clear winner here, especially with higher amount of remeshing iterations.
There are, however, a few issues I can see with the results:

  1. The algorithm doesn't seem to change the mesh when target edge length is set to exceed the longest edge (in this case >4.5)
  2. GC and cinolib refine the mesh with each remeshing iteration. MeshLib seems to only work once.
  3. MeshLib is quite inconsistent - notice how some portions of the mesh are mor refined than the others:
    image

For reference, here is how I call this function:

	RemeshSettings settings = RemeshSettings();
	settings.targetEdgeLen = targetLength;
	settings.packMesh = true;
	settings.maxAngleChangeAfterFlip = 30 * PI_F / 180.0f;

	for (int i = 0; i < iterations; i++ )
		remesh( *mesh, settings );

Cut off part feature of the mesh model

Hello,If I use a plane to cut off a model, can I cut off some mesh features?For example, I want to cut off the A feature of the mesh model, but I don't want to cut off the B feature of the mesh model.
8026feec4a602a13d8f0fd999024439
Is there any better way to solve this problem?

offset on a very simple mesh crashes my Ubuntu VM

I have this simple stl file of 4 triangles, very simple (the attached file is an stl file renamed as txt).
Running this python code, the memory increase till the crash of the VM:

mesh= mrmeshpy.loadMesh(fn)

params = mrmeshpy.OffsetParameters()
params.voxelSize = 0.0
params.type = mrmeshpy.OffsetParametersType.Shell

shell = mrmeshpy.offsetMesh(mesh, -2, params)

Can you check, please?

Thanks
Fabio

Meshlib 2.1.6
aaaaaaa_TH4.2000.txt

Volumetric Difference between meshes

I'm trying to compare two meshes and compute the volume difference between them. Here is a simple illustration. The cyan mesh (A) is sometimes higher, sometimes lower and sometimes at the same elevation as the magenta mesh (B). Sometimes there is no overlap at all:
image

Cross-sectional view to better illustrate the relationship between these two objects:
image

I'd like to calculate the difference between them and split it into cut (A is below B), and fill (A is above B). The results would be returned both as numerical values and as a heatmap on a resulting mesh. Here is an example from Wikipedia
image

My approach would be to:

  1. Retrieve a bounding box of both meshes
  2. Populate it with a regular grid of points
  3. Shoot rays from each of the points
  4. Calculate the distance between hit points and save the results
  5. Construct a mesh from the grid of points and visualize the results using vertex colors for each of the points

It's relatively simple to implement but the results would be heavily dependent on the resolution of the point grid and it would be hard to trace the exact isolines where meshes transition from cut to fill. Furthermore, I'd like the result to be a series of closed solid meshes as opposed to an open surface mesh.

image

Do you have better ideas on how to approach this?

Whether meshlib supports running on the browser through wasm

I'm interested in meshlib, which has a lot of features I need, and I want to use it in the browser to improve the efficiency of 3D operations. Does meshlib support converting to wasm to run in a browser? If there is a feasible plan can you provide some ideas?

PointCloud sampling

Hello!

I'm dealing with relatively large point-clouds (5-10M points). For my workflow, I need to sample these with a regular grid of approx. 10 000 sample points and find the id of the closest points from the point cloud to each sample point.

In Rhino 5M points and 10 000 samples takes approx. 20s to compute. Do you think MeshLib could do this faster?

I need this for a wind simulation study. Here is an example for a much smaller point cloud which runs in real-time:
image

https://www.youtube.com/watch?v=l33cxovz_3I

Debugging issues

When I use library files for debugging,Can I have a link to the source code?
4e848cd15ac4976ec4fc4c5084adfbc
Can I debug directly into the cpp file?
d2be4c2e4896502ac4cd1b67a9b6e9c
I want to see other data during the debugging process
f4423f2e59e1a1523b48a88b81b4190

python decimation

When I use decimation the mesh is torn to pieces. How to get rid of it?

import meshlib

name = meshlib.mrmeshpy.Path('jaw.stm')
mesh = meshlib.mrmeshpy.loadMesh(name)
outFaces = meshlib.mrmeshnumpy.getNumpyFaces(mesh.topology)
print(outFaces.shape[0])    # 249319

settings = meshlib.mrmeshpy.DecimateSettings()
settings.maxDeletedFaces = outFaces.shape[0] - 10000
settings.packMesh = True
dec_mesh = meshlib.mrmeshpy.decimateMesh(mesh, settings)

jaw

Add Box3f functions to python

Please, add functions to python - include(Vector3f ), include( const Box & b ), Box & intersect( const Box & b ), contains() , volume()

nearly overlaping triangles split

If the mesh have overlapping triangles ,it is easy to resolve this problems I guess, just split triangles.But if the mesh has many nearly overlapping triangles,(this triangles In theory, are not coplanar due to floating-point error),
I used a lot of free softwares, like meshlab meshmixer etc,none of them have this function, I think models with such flaws are common
,Do you have plan to solve this problem?

Mesh Segmentation

Hey,

I am trying to segment a mesh using MeshLib, I am not able to find the related source library or example. Do you an example for it?
Assuming this input mesh:

import meshlib.mrmeshpy as mrmeshpy
 
try:
    mesh = mrmeshpy.loadMesh(mrmeshpy.Path("mesh.stl"))
except ValueError as e:
    print(e)

Thanks!

Best,
Ahmad

python filling hole(and stitching two holes) with same result as MeshInspector

Hello,

I'm testing stitching_two_holes function using python code which is similar to here, but got bad result in some cases. For example, (1) very narrow triangle directly linking the two hole border even after subdivision. (2) or the result mesh is exploded. I modified some filing hole configurations but cannot solve those problems. Besides, because we cannot modify the mesh's existing region when filing holes, I need to set SubdivideSettings.subdivideBorder=False(but this cannot avoid problems).

I tested the meshInspector's stitching_two_holes function, and it works correctly on my test meshes. I wonder if you can provide some sample code which can get same result as MeshInspector. With that, we can compare hole filling result with meshinspector directly when we encountered bad result. And it will be much convenient to report problems to you.

Thanks.

Curved cylinder

Is there a algorithm that can convert 3d polyline to a triangle mesh as shown above?
image
image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.