Giter VIP home page Giter VIP logo

Comments (7)

Grantim avatar Grantim commented on May 18, 2024 1

We are now relay on elements order in memory when reading numpy arrays, thats why it loads incorrectly

import numpy as np
from meshlib import mrmeshpy as mm
from meshlib import mrmeshnumpy as mn


verts = np.load("verts.npy")
#make 'C' order for this array
vShape = verts.shape
verts = verts.flatten().reshape(vShape)
#change dtype to int32 and make 'C' order
faces = np.load("faces.npy").astype(np.int32,order='C');

mesh = mn.meshFromFacesVerts(faces, verts)

mm.saveMesh(mesh, "mesh.ply")

Looks like this should work, anyway we will try to improve this in future.
Thanks!

from meshlib.

sysuyl avatar sysuyl commented on May 18, 2024

I have adjusted some subdivision configurations to avoid narrow triangles successfully.

But there is still exploded result on some cases. I found it occurs after function buildCylinderBetweenTwoHoles. I tried the available metrics(the default one and the getEdgeLengthStitchMetric), both failed. Besides, the MeshInspector can stitching two holes(triangulate only) with different metrics.

Here is my test data.
test_data.zip

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

Hello, can you please send code sample that you tried, it result looks very strange
image

from meshlib.

sysuyl avatar sysuyl commented on May 18, 2024

hello, the core code is like this,

def stitch_mesh_two_holes(mesh, he1, he2):
    # Create parameters for filling hole
    params = mrmesh.StitchHolesParams()
    newFacesBitSet = mrmesh.FaceBitSet()
    params.outNewFaces = newFacesBitSet
    params.metric = mrmesh.getEdgeLengthStitchMetric(mesh)

    mrmesh.buildCylinderBetweenTwoHoles(mesh, he1, he2, params) 

    return mesh, newFacesBitSet

Yes, the result looks very strange. Let me try debugging again, I have just discovered some new details.

from meshlib.

Grantim avatar Grantim commented on May 18, 2024

I have checked

from meshlib import mrmeshpy as mm

mesh = mm.loadMesh("test_input.ply")

holes = mesh.topology.findHoleRepresentiveEdges()

newFacesBitSet= mm.FaceBitSet()
params = mm.StitchHolesParams()
params.outNewFaces = newFacesBitSet
params.metric = mm.getEdgeLengthStitchMetric(mesh)
mm.buildCylinderBetweenTwoHoles(mesh,holes[0],holes[1], params)

# subdivide new faces only
settings = mm.SubdivideSettings()
settings.maxEdgeLen = 0.2
settings.maxEdgeSplits = 100000
settings.maxDeviationAfterFlip = 0.2
settings.region = newFacesBitSet
# accum new verts after subdivide for optional curvature positioning
newVertsBitSet = mm.VertBitSet()
settings.newVerts = newVertsBitSet

mm.subdivideMesh(mesh, settings)

# optional positioning
mm.positionVertsSmoothly(mesh, newVertsBitSet)

mm.saveMesh(mesh, mm.Path("res.ply"))

and got such result
image
res.zip

from meshlib.

Grantim avatar Grantim commented on May 18, 2024
from meshlib import mrmeshpy as mm


def stitch(mesh, he1, he2):
	# Create parameters for filling hole
    params = mm.StitchHolesParams()
    newFacesBitSet = mm.FaceBitSet()
    params.outNewFaces = newFacesBitSet
    params.metric = mm.getEdgeLengthStitchMetric(mesh)

    mm.buildCylinderBetweenTwoHoles(mesh, he1, he2, params) 

    return mesh, newFacesBitSet


mesh1 = mm.loadMesh("test_input.ply")

holes = mesh1.topology.findHoleRepresentiveEdges()
mesh, newFacesBitSet = stitch(mesh1,holes[0],holes[1])

# subdivide new faces only
settings = mm.SubdivideSettings()
settings.maxEdgeLen = 0.2
settings.maxEdgeSplits = 100000
settings.maxDeviationAfterFlip = 0.2
settings.region = newFacesBitSet
# accum new verts after subdivide for optional curvature positioning
newVertsBitSet = mm.VertBitSet()
settings.newVerts = newVertsBitSet

mm.subdivideMesh(mesh, settings)

# optional positioning
mm.positionVertsSmoothly(mesh, newVertsBitSet)

mm.saveMesh(mesh, mm.Path("res2.ply"))

gave the same result as #1402 (comment)

from meshlib.

sysuyl avatar sysuyl commented on May 18, 2024

Hello,

I found that the problem may be from the numpy_mrmesh_conversion code(in my test code below). The conversion is good for most of meshes I tested, but failed with the one here. I saved the testing mesh to npy format to show the problem, because the conversion will be correct after writing and reading back with ply format.

The test mesh data(npy format),
test_mesh_npy.zip

Below is my test code. It reads the npy mesh, and prints some mesh information to compare. The problem is, if directly converting the npy mesh using numpy_mrmesh_conversion code(mrmesh_from_numpy, mrmesh_to_numpy), the mesh will change a lot and look strange.

import numpy as np


def read_mesh_trimesh(filename):
    import trimesh

    mesh = trimesh.load(filename)
    v, f = mesh.vertices, mesh.faces
    v = np.array(v)[:, :3].astype(np.float32)
    f = np.array(f)[:, :3].astype(np.int32)
    return v, f


def write_mesh_trimesh(filename, v, f):
    import trimesh
    mesh = trimesh.Trimesh(v, f)
    mesh.export(filename)


def read_mesh_igl(filename):
    import igl
    v, f = igl.read_triangle_mesh(filename)
    return v, f


def write_mesh_igl(filename, v, f):
    import igl
    igl.write_triangle_mesh(filename, v, f)
    return v, f


def mrmesh_from_numpy(verts, faces):
    from meshlib import mrmeshpy as mm
    import meshlib.mrmeshnumpy as mrmeshnumpy
    verts, faces = verts.astype(np.float32), faces.astype(np.int32)
    mesh = mrmeshnumpy.meshFromFacesVerts(faces, verts)
    return mesh


def mrmesh_to_numpy(mesh):
    from meshlib import mrmeshpy as mm
    import meshlib.mrmeshnumpy as mrmeshnumpy
    verts = mrmeshnumpy.getNumpyVerts(mesh)
    faces = mrmeshnumpy.getNumpyFaces(mesh.topology)
    return verts, faces


def test():
    # python 3.8.15
    # meshlib version: 2.1.9
    # trimesh version: 3.17.1
    # igl version: 2.2.1

    verts = np.load("verts.npy")
    faces = np.load("faces.npy")

    print("\n## ----- input")
    print("#v, #f: ", verts.shape, faces.shape)
    print("sum: ", np.sum(verts))
    print("mean: ", np.mean(verts, axis=0))

    # write and read with trimesh
    print("\n## ----- trimesh")
    write_mesh_trimesh("trimesh.ply", verts, faces)
    verts_tri, faces_tri = read_mesh_trimesh("trimesh.ply")
    print("#v, #f: ", verts_tri.shape, faces_tri.shape)
    print("sum: ", np.sum(verts_tri))
    print("mean: ", np.mean(verts_tri, axis=0))

    # write and read with trimesh
    print("\n## ----- igl")
    write_mesh_igl("igl.ply", verts, faces)
    verts_igl, faces_igl = read_mesh_igl("igl.ply")
    print("#v, #f: ", verts_igl.shape, faces_igl.shape)
    print("sum: ", np.sum(verts_igl))
    print("mean: ", np.mean(verts_igl, axis=0))

    # to and from mrmesh
    print("\n## ----- mrmesh1, from numpy data")
    mesh = mrmesh_from_numpy(verts, faces)
    verts_mr, faces_mr = mrmesh_to_numpy(mesh)
    print("#v, #f: ", verts_mr.shape, faces_mr.shape)
    print("sum_mr: ", np.sum(verts_mr))
    print("mean: ", np.mean(verts_mr, axis=0))
    write_mesh_trimesh("mr_numpy.ply", verts_mr, faces_mr)

    # # to and from mrmesh using the trimesh one
    print("\n## ----- mrmesh2, from trimesh read")
    mesh = mrmesh_from_numpy(verts_tri, faces_tri)
    verts_mr, faces_mr = mrmesh_to_numpy(mesh)
    print("#v, #f: ", verts_mr.shape, faces_mr.shape)
    print("sum: ", np.sum(verts_mr))
    print("mean: ", np.mean(verts_mr, axis=0))
    write_mesh_trimesh("mr_trimesh.ply", verts_mr, faces_mr)

    # # to and from mrmesh using the igl one
    print("\n## ----- mrmesh2, from igl read")
    mesh = mrmesh_from_numpy(verts_igl, faces_igl)
    verts_mr, faces_mr = mrmesh_to_numpy(mesh)
    print("#v, #f: ", verts_mr.shape, faces_mr.shape)
    print("sum: ", np.sum(verts_mr))
    print("mean: ", np.mean(verts_mr, axis=0))
    write_mesh_trimesh("mr_igl.ply", verts_mr, faces_mr)


test()

And below is the console output,

## ----- input
#v, #f:  (8828, 3) (17090, 3)
sum:  906109.3522396502
mean:  [49.09825646 17.08983528 36.45229705]

## ----- trimesh
#v, #f:  (8828, 3) (17090, 3)
sum:  906109.4
mean:  [49.098206 17.089834 36.452335]

## ----- igl
#v, #f:  (8828, 3) (17090, 3)
sum:  906109.3522396502
mean:  [49.09825646 17.08983528 36.45229705]

## ----- mrmesh1, from numpy data
#v, #f:  (8828, 3) (17074, 3)
sum_mr:  906109.3521671295
mean:  [34.19764061 34.22750484 34.21524333]

## ----- mrmesh2, from trimesh read
#v, #f:  (8828, 3) (17090, 3)
sum:  906109.3521671295
mean:  [49.09825644 17.08983529 36.45229705]

## ----- mrmesh2, from igl read
#v, #f:  (8828, 3) (17090, 3)
sum:  906109.3521671295
mean:  [49.09825644 17.08983529 36.45229705]

And below is the output files,

res.zip

from meshlib.

Related Issues (20)

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.