Comments (17)
Hi Petras,
These are a couple of extension methods I wrote to convert from Dmesh3 to Rhino meshes and back. Only imports vertices and faces (recalculates normals in Rhino) you could also add uvs, colors and so on. Usage would be " var rhinoMesh = mesh.ToRhinoMesh() and var g3Mesh = rhinoMesh.ToDMesh3():
public static DMesh3 ToDMesh3(this Mesh mesh)
{
var dMesh3 = new DMesh3();
for (int i = 0; i < mesh.Vertices.Count; i++)
{
var vertex = mesh.Vertices[i];
var normal = mesh.Normals[i];
NewVertexInfo ni = new NewVertexInfo()
{
v = new g3.Vector3d(vertex.X, vertex.Z, vertex.Y),
n = new g3.Vector3f(normal.X, normal.Z, normal.Y)
};
dMesh3.AppendVertex(ni);
}
foreach (var face in mesh.Faces)
{
dMesh3.AppendTriangle(face.A, face.B, face.C);
}
return dMesh3;
}
public static Mesh ToRhinoMesh(this DMesh3 dMesh3)
{
dMesh3 = new DMesh3(dMesh3, true, MeshComponents.All);
var mesh = new Mesh();
var vertices = dMesh3.Vertices().Select(v => new Point3d(v.x, v.z, v.y));
var faces = dMesh3.Triangles().Select(f => new MeshFace(f.a, f.b, f.c));
mesh.Vertices.AddVertices(vertices);
mesh.Faces.AddFaces(faces);
mesh.Normals.ComputeNormals();
mesh.Compact();
return mesh;
}
from geometry3sharp.
Does the make_good_cylinder() function do Remeshing internally, or other mesh composition operations?
If you construct a DMesh3 from scratch, it will have the same properties as other indexed meshes, ie dense index space. But if you do things like Remeshing, it will leave 'holes' in the index space as it deletes vertices/triangles.
To get back to a Dense index space you have to compact the mesh. The fastest way to do that is to use the compacting copy constructor. IE you could write:
g3m = new g3.DMesh3(g3m, true);
and now g3m will have dense index spaces.
from geometry3sharp.
Thanks it works.
I would like to ask about remeshing part.
I see that after remeshing you apply smoothing. But in this case the original mesh shape changes.
Is it possible to remesh a mesh in such a way that its its edges will be more or less equilateral and output shape would be the same (without smoothing)?
I am using your example file with cylinder:
public DMesh3 make_good_cylinder(float fResScale = 1.0f) {
DMesh3 mesh = MakeCappedCylinder(false);
MeshUtil.ScaleMesh(mesh, Frame3f.Identity, new g3.Vector3f(1, 2, 1));
mesh.CheckValidity();
Remesher r = new Remesher(mesh);
r.EnableFlips = r.EnableSplits = r.EnableCollapses = true;
r.MinEdgeLength = 0.1f * fResScale;
r.MaxEdgeLength = 0.2f * fResScale;
r.EnableSmoothing = true;
r.SmoothSpeedT = 0.1f;
r.EnableFlips = r.EnableSmoothing = false;
r.MinEdgeLength = 0.05f * fResScale;
for ( int k = 0; k < 10; ++k ) {
r.BasicRemeshPass();
mesh.CheckValidity();
}
r.MinEdgeLength = 0.1f * fResScale;
r.MaxEdgeLength = 0.2f * fResScale;
r.EnableFlips = r.EnableCollapses = r.EnableSmoothing = true;
for ( int k = 0; k < 100; ++k ) {
r.BasicRemeshPass();
mesh.CheckValidity();
}
return mesh;
}
from geometry3sharp.
It seems that this function does what I want:
test_remesh_constraints_fixedverts
Would it also work for open meshes? Lets say if cylinder is not capped?
from geometry3sharp.
Nice works with open one too.
Is this library totally C# ? Or it has dependencies
from geometry3sharp.
it is completely in C# and has no dependencies.
from geometry3sharp.
Thanks, maybe you know what is a proper way of checking mesh winding order?
The posts I searched, usually starts with cross product - normal of face. Then there is a construction of transformation matrix.
But what is the proper way of checking the winding if it is clockwise or anti-clockwise?
public bool Triangle(Vector3f v0, Vector3f v1, Vector3f v2)
{
Vector3f axis_x = v1 - v0; // edge v0 -> v1
Vector3f axis_y = v2 - v0; // edge v0 -> v2
Vector3f cross = Vector3f.CrossProduct(axis_x, axis_y);
cross.Unitize();
....
}
This is just normal calculation of mesh face, what it must change if it is clockwise of anti-clockwise.
from geometry3sharp.
Is that question related to the g3 geometric library or is it a general computer graphics question?
(if it's the second one, i guess Ryan might prefer you ask it in StackOverflow :P)
from geometry3sharp.
I know...
If there is method in g3 to point me to winding would be preferable.
from geometry3sharp.
Probably it boils down to
find the edge that both faces share, and then see if the edges
are reversed in order as you would expect in a well constructed
from geometry3sharp.
Are you trying to fix a mesh that has faces with different winding or are you trying to figure out which convention this library uses?
If it's the latter, we can check the code to figure out the face normal:
public static Vector3d Normal(Vector3d v1, Vector3d v2, Vector3d v3) {
Vector3d edge1 = v2 - v1;
Vector3d edge2 = v3 - v2;
edge1.Normalize();
edge2.Normalize();
Vector3d vCross = edge1.Cross(edge2);
vCross.Normalize();
return vCross;
}
If you then look at this diagram: https://en.wikipedia.org/wiki/Cross_product#/media/File:Right_hand_rule_cross_product.svg
(assuming he implemented the "Cross" method following the right hand coordinate system)
you can deduce he uses CCW convention for winding.
from geometry3sharp.
It is about fixing.
Yap, the directionality define by your function of calculating mesh face normal.
But for checking whole mesh if mesh face windings are correct, you probably need to start from arbitrary mesh face and loop through neighbour faces and swapping their direction if edge direction does not match .
from geometry3sharp.
the Cross Product does not change if you use RHS or LHS coordinate systems. Switching coordinate systems involves switching the basis vectors, which then changes the interpretation of the result of a cross product. But the formula doesn't change.
Most of the library is not specific to a particular coordinate system. For example Unity is LHS but many (perhaps most) other tools are RHS. There are functions in MeshTransform to switch between these two when necessary.
A mesh doesn't have "sides" so any set of vertices and triangles can be oriented such that the normals computed from face-edge-cross-products point outwards or inwards. You switch this just by switching the order of the vertices in the face.
'fixing' a mesh with inconsistent per-triangle orientations can be quite difficult. The process you describe - fix one face and then propagate across neighbour edges - works if the mesh is closed and orientable (ie manifold). The standard process is to do something like a raycast from far away, set the orientation/winding of the face the ray hits to be the orientation/winding you want (ie face normal should point towards ray, under whatever handedness-system you want to use), and then do the propagation.
If the mesh is not closed, this will produce one of the two possible orientations depending on where the ray hits. If the mesh has disjoint regions this can lead to them being "incorrectly" oriented relative to what a human might have been hoping for.
I do intend to eventually implement the fix-and-propagate part of orientation repair in the library, just haven't gotten to it yet.
from geometry3sharp.
Thanks for the explanation. Fixing winding looks like not a straight forward process.
I have additional question about remeshing.
I am using one of your functions for remeshing, I tried to change angle and other properties, but I corners points of this box are not fixed. How to snap these corner points correctly?
public DMesh3 test_remesh_constraints_fixedverts(int iterations, DMesh3 mesh, double min, double max,double angle)
{
AxisAlignedBox3d bounds = mesh.CachedBounds;
// construct mesh projection target
DMesh3 meshCopy = new DMesh3(mesh);
meshCopy.CheckValidity();
DMeshAABBTree3 tree = new DMeshAABBTree3(meshCopy);
tree.Build();
MeshProjectionTarget target = new MeshProjectionTarget() { Mesh = meshCopy, Spatial = tree };
// construct constraint set
MeshConstraints cons = new MeshConstraints();
//EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip | EdgeRefineFlags.NoCollapse;
EdgeRefineFlags useFlags = EdgeRefineFlags.NoFlip;
foreach (int eid in mesh.EdgeIndices()) {
double fAngle = MeshUtil.OpeningAngleD(mesh, eid);
if (fAngle > angle) {
cons.SetOrUpdateEdgeConstraint(eid, new EdgeConstraint(useFlags));
Index2i ev = mesh.GetEdgeV(eid);
int nSetID0 = (mesh.GetVertex(ev[0]).y > bounds.Center.y) ? 1 : 2;
int nSetID1 = (mesh.GetVertex(ev[1]).y > bounds.Center.y) ? 1 : 2;
cons.SetOrUpdateVertexConstraint(ev[0], new VertexConstraint(true, nSetID0));
cons.SetOrUpdateVertexConstraint(ev[1], new VertexConstraint(true, nSetID1));
}
}
Remesher r = new Remesher(mesh);
r.Precompute();
r.SetExternalConstraints(cons);
r.SetProjectionTarget(target);
r.EnableFlips = r.EnableSplits = r.EnableCollapses = true;
r.MinEdgeLength = min;
r.MaxEdgeLength = max;
r.EnableSmoothing = true;
r.SmoothSpeedT = 1;
for (int k = 0; k < iterations; ++k) {
r.BasicRemeshPass();
mesh.CheckValidity();
}
return mesh;
}
from geometry3sharp.
the Cross Product does not change if you use RHS or LHS coordinate systems.
Unity's cross product method follows the LHS. I'm sure the math is the same, but the order of the vector parameters is reversed, which could also be the case in this library if you don't look at the code https://docs.unity3d.com/ScriptReference/Vector3.Cross.html).
A mesh doesn't have "sides"
Well, the direction the face normal are pointing are important for many things, like rendering (back-face culling, refraction) or Boolean operations. I guess the remesher of this library is not affected by this.
from geometry3sharp.
@petrasvestartas This is happening because the Remesher needs to know about the sets of edges you want to preserve. In the sample code the object is a cylinder. Guessing the "sharp" edges is done by the (fAngle > angle) test.
However then in the next few lines I am checking if the vertex is above or below the bounding-box center (the nSetID0 and nSetID1 variables). These values are passed into the VertexConstraint constructor. This is a hacky way to "find" the upper and lower creases on the cylinder.
Basically, the remesher is treating these as "sets" of related vertices/edges. It is allowed to collapse to other vertices in the set, but not across sets. So for your cube it means all the sharp edges in the upper half / lower half are fair game for collapsing, and what is happening is the corner vertices are being lost.
The way to fix this is to tag the corner vertices with their own set ID. However to do that you have to find the corners. One way would be to count the 'sharp' edges coming out of each vertex. If there are more than 2, it is a corner.
(this might be improved in the future because clearly the edge constraints should also have these set IDs, and in that case I could handle these "corner" situations automatically...)
from geometry3sharp.
Hello,
Is it possible to know which function prevents vertex from moving (make it fixed)
(I know the vertex ID number)
from geometry3sharp.
Related Issues (20)
- Convert mesh regions to 2d, alter in 2d, push back into 3d mesh
- Is this project dead? HOT 1
- Get brick materials right
- Fix hover info on bricks
- Rewrite right pointer (PLEASE!) HOT 1
- Mesh expansion and comparison
- Refactor cursor3d
- Refactor HandR and HandL to use input action class
- Write playmode tests for right pointer flow
- Rider clean project to adjust line length
- Break up LDrawConfig into different classes
- Refactor BrickMaterialsLoader (PLEASE!!!)
- Example of mesh volume calculation HOT 3
- 这个可以做曲面拟合吗?
- Can this be used for surface fitting?
- Narrow band SDF generation from meshes is adding a shell to objects HOT 1
- Minkowski sum 3D
- Get closest vertex on mesh surface HOT 2
- Boolean operations on polygons and polyhedra?
- Quadratic Bezier Curves HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from geometry3sharp.