-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using Manifold in Unity causes normals errors #1151
Comments
I can't see where you use the normal computed in manifold in your prototype code. And I think you should be careful with the |
Oh thanks! Can you provide some pointers as to how to retrieve set and retrieve the normals in Manifold? I've been unsuccessful in learning how in the samples/docs sorry. |
Looking at it, the C# fork seems to be a bit outdated (6 months ago). I forgot if we fixed any bug related to this in the last 6 months. I guess it should be possible to patch our current head using the updates in the fork and build a C# library. |
You probably need to call |
Actually I took the fork bindings and used the latest build here. So Manifold itself is up to date and luckily the API doesn't appear to have changed.
|
Okay I see - Yes the bindings didn't have it. But I've added it now. It's not clear to me how its meant to be used - Should I call I've tried both with |
Iirc you should use |
You might be right. I have tried it with 0 to no avail sadly. |
Now that you've passed in the normals, can you by chance show a render that actually draws your normals as little vectors? I'd guess that you used to have multiple normals per vert and now you don't. You shouldn't recalculate any normals if they're being passed in properly. You'll need to make use of the merge vectors in |
Yes, this is the issue, and I've gotten enough questions about how to use Just like with GL buffers, anywhere you have different properties meeting at the same vertex, that vertex must be duplicated. The only difference is we add the |
Okay that makes sense in theory to me. It's still not quite clear to me exactly what should go in the structures having read the code comments: /// Optional: A list of only the vertex indicies that need to be merged to
/// reconstruct the manifold.
std::vector<I> mergeFromVert;
/// Optional: The same length as mergeFromVert, and the corresponding value
/// contains the vertex to merge with. It will have an identical position, but
/// the other properties may differ.
std::vector<I> mergeToVert; Right now per my code, I'm iterating over the triangle indices and giving just those vectors and normals. These same vector indices should go into Here is my attempt at it below. It is untested because I assume I need to run public static ManifoldNET.MeshGL GetManifoldMeshFromMesh(MeshFilter meshFilter)
{
Mesh mesh = meshFilter.sharedMesh;
Transform transform = meshFilter.transform;
var vertProperties = new List<float>();
var triVerts = new List<uint>();
var mergeFromVert = new List<int>();
var mergeToVert = new List<int>();
Matrix4x4 localToWorld = transform.localToWorldMatrix;
Dictionary<(Vector3 pos, Vector3 normal, Vector2 uv), uint> uniqueVerts = new Dictionary<(Vector3, Vector3, Vector2), uint>();
for(int i = 0; i < mesh.triangles.Length; i++)
{
int triIndex = mesh.triangles[i];
Vector3 v = mesh.vertices[triIndex];
Vector3 normal = mesh.normals[triIndex];
Vector2 uv = mesh.uv.Length > 0 ? mesh.uv[triIndex] : Vector2.zero;
// Convert to world space
v = localToWorld.MultiplyPoint3x4(v);
normal = localToWorld.MultiplyVector(normal).normalized;
// Convert Unity Y-Up to Manifold Z-Up
v = new Vector3(v.x, v.z, -v.y);
normal = new Vector3(normal.x, normal.z, -normal.y);
var key = (v, normal, uv);
if(!uniqueVerts.TryGetValue(key, out uint index))
{
index = (uint)uniqueVerts.Count;
uniqueVerts[key] = index;
vertProperties.Add(v.x);
vertProperties.Add(v.y);
vertProperties.Add(v.z);
}
else
{
// Track duplicate vertices that should be merged
mergeFromVert.Add((int)index);
mergeToVert.Add((int)uniqueVerts[key]);
}
triVerts.Add(index);
}
// Reverse triangle winding for Manifold
//for(int i = 0; i < triVerts.Count; i += 3)
//{
// (triVerts[i + 1], triVerts[i + 2]) = (triVerts[i + 2], triVerts[i + 1]);
//}
var meshGL = new ManifoldNET.MeshGL(vertProperties.ToArray(), triVerts.ToArray());
meshGL.MergeFromVert = mergeFromVert.ToArray();
meshGL.MergeToVert = mergeToVert.ToArray();
meshGL.Merge();
return meshGL;
}
public static Mesh GetMeshFromManifold(Manifold manifold, Transform originalTransform)
{
var mesh = new Mesh();
var meshGL = manifold.GetMeshGL(0);
int vertCount = meshGL.VerticesNumber;
int propCount = meshGL.PropertiesNumber;
int vertOffset = 0;
var worldToLocal = originalTransform.worldToLocalMatrix;
var verts = new Vector3[vertCount];
var normals = new Vector3[vertCount];
var meshGLVerts = meshGL.VerticesProperties;
// Convert from Manifold back to Unity
for(int i = 0; i < vertCount; i++)
{
verts[i] = new Vector3(
meshGLVerts[vertOffset], // X
-meshGLVerts[vertOffset + 2], // Flip Y back
meshGLVerts[vertOffset + 1] // Swap Y and Z back
);
verts[i] = worldToLocal.MultiplyPoint3x4(verts[i]);
if(propCount > 3)
{
normals[i] = new Vector3(
meshGLVerts[vertOffset + 3],
-meshGLVerts[vertOffset + 5], // Flip Y back
meshGLVerts[vertOffset + 4] // Swap Y and Z back
).normalized;
}
vertOffset += propCount;
}
// Apply merging information to remove duplicate vertices
var mergeFrom = meshGL.MergeFromVert;
var mergeTo = meshGL.MergeToVert;
if(mergeFrom.Length > 0 && mergeTo.Length > 0)
{
for(int i = 0; i < mergeFrom.Length; i++)
{
int fromIndex = (int)mergeFrom[i];
int toIndex = (int)mergeTo[i];
// Merge vertex positions and normals
verts[fromIndex] = verts[toIndex];
normals[fromIndex] = normals[toIndex];
}
}
// Assign data to Unity Mesh
mesh.vertices = verts;
mesh.normals = normals;
mesh.triangles = meshGL.TriangleVertices.Select(t => (int)t).ToArray();
// Ensure correct normals and tangents for shading
mesh.RecalculateBounds();
mesh.RecalculateTangents(); // Needed for correct lighting in normal-mapped materials
return mesh;
} |
So, it looks like Unity (as with most graphics programs) already stores their info in effectively It looks like your For |
I am unfortunately running into an issue here where |
I've been testing out Manifold for a usecase in a video game using the Unity engine. I've been able to setup bindings and figure out how to get mesh data to and from Manifold. However I've run into an issue where it looks like the normals are malformed:

I'd love some help in understanding what I might be doing wrong.
Note I've had to convert the verts Y-Up → Z-Up as it appears Unity and Manifold operation in different formats. I also briefly toyed with triangle winding conversions, but it broke things - Could it be one or both of these aren't done correctly?
Prototype code in Unity:
The text was updated successfully, but these errors were encountered: