Hello guys. Im making a Rhino plugin that needs to reduce a mesh if its above a certain face count. However I’m running into an issue where im getting a nullreferece error on the reduce process. I cannot seem to figure this out. Any help would be appreciated!
DEBUG: docMesh.Reduce(…) threw an exception: NullReferenceException => Object reference not set to an instance of an object.DEBUG: docMesh.Reduce(…) threw an exception: NullReferenceException => Object reference not set to an instance of an object.
// STEP 7: Reduce if facecount > 5k (document-owned approach, 90% reduction) with extra debug
foreach (var meshPiece in pieces)
{
// Debug: Checking face count of meshPiece
if (meshPiece == null)
{
RhinoApp.WriteLine("DEBUG: meshPiece is null at the start of the loop.");
continue;
}
int faceCountDebug = meshPiece.Faces.Count;
RhinoApp.WriteLine($"DEBUG: meshPiece is NOT null. It currently has {faceCountDebug} faces.");
// Now do the threshold check
RhinoApp.WriteLine($"FaceCount checked {faceCountDebug}");
if (faceCountDebug <= 5000)
{
RhinoApp.WriteLine($"Low Polygon Count (<=5k). We skip reduce. FaceCount is {faceCountDebug}.");
continue; // skip smaller meshes
}
RhinoApp.WriteLine($"Before reduction: {faceCountDebug} faces");
// 1) Create a doc object from meshPiece
RhinoApp.WriteLine("DEBUG: About to add meshPiece to doc as a new mesh object.");
Guid pieceId = doc.Objects.AddMesh(meshPiece);
RhinoApp.WriteLine($"DEBUG: Added doc object with ID: {pieceId}");
doc.Views.Redraw();
// Confirm meshPiece is still not null
if (meshPiece == null)
{
RhinoApp.WriteLine("DEBUG: meshPiece became null AFTER adding to doc (unexpected). Skipping reduce.");
continue; // or handle differently
}
// 2) Retrieve the Mesh from the doc
RhinoApp.WriteLine($"DEBUG: Attempting to find doc object by pieceId: {pieceId}");
RhinoObject docObj = doc.Objects.Find(pieceId);
if (docObj == null)
{
RhinoApp.WriteLine("DEBUG: docObj is null => we cannot find the newly added object in doc.");
continue;
}
// Check if docObj.Geometry is a Mesh
var docMesh = docObj.Geometry as Mesh;
if (docMesh == null)
{
RhinoApp.WriteLine("Warning: docObj is not a Mesh. Possibly invalid geometry?");
continue;
}
RhinoApp.WriteLine($"DEBUG: docMesh is valid. docMesh.Faces.Count = {docMesh.Faces.Count}");
// 3) (Optional) Clean up docMesh
RhinoApp.WriteLine("DEBUG: About to run docMesh cleanup steps (Compact, CullDegenerate, etc.)");
docMesh.Compact();
docMesh.Faces.CullDegenerateFaces();
docMesh.Vertices.CombineIdentical(true, true);
docMesh.Vertices.CullUnused();
docMesh.Normals.ComputeNormals();
docMesh.UnifyNormals();
docMesh.Compact();
RhinoApp.WriteLine($"DEBUG: docMesh cleanup done. Faces now = {docMesh.Faces.Count}.");
// 4) Prepare reduce parameters
int faceCount = docMesh.Faces.Count;
RhinoApp.WriteLine($"DEBUG: Current docMesh faceCount after cleanup: {faceCount}");
int targetCount = (int)(faceCount * 0.1); // keep 10%, reduce by 90%
var reduceParams = new ReduceMeshParameters
{
DesiredPolygonCount = targetCount
// e.g. reduceParams.AllowDistortion = false;
// reduceParams.Accuracy = 5;
};
RhinoApp.WriteLine($"DEBUG: reduceParams set => DesiredPolygonCount = {targetCount}.");
// Double-check docMesh validity
if (!docMesh.IsValid || docMesh.Faces.Count == 0)
{
RhinoApp.WriteLine($"DEBUG: docMesh invalid or no faces before reduce. docMesh.Faces.Count={docMesh.Faces.Count}");
continue;
}
// 5) Attempt to reduce docMesh
RhinoApp.WriteLine("DEBUG: About to call docMesh.Reduce(...) now. Cross fingers!");
bool ok = false;
try
{
ok = docMesh.Reduce(reduceParams);
}
catch (Exception ex)
{
RhinoApp.WriteLine($"DEBUG: docMesh.Reduce(...) threw an exception: {ex.GetType().Name} => {ex.Message}");
continue;
}
if (!ok)
{
RhinoApp.WriteLine("Warning: reduce method returned false or was unable to reduce.");
continue;
}
// 6) Print updated face count
int newCount = docMesh.Faces.Count;
RhinoApp.WriteLine($"After reduction: {newCount} faces");
// 7) Overwrite meshPiece if we want to keep the final geometry in memory
RhinoApp.WriteLine("DEBUG: About to copy docMesh changes back into meshPiece.");
try
{
meshPiece.CopyFrom(docMesh);
}
catch (Exception ex)
{
RhinoApp.WriteLine($"DEBUG: meshPiece.CopyFrom(docMesh) threw: {ex.GetType().Name} => {ex.Message}");
}
// 8) Optionally, remove from doc if you only want the final pieces[] in memory
// doc.Objects.Delete(pieceId, true);
// doc.Views.Redraw();
RhinoApp.WriteLine("DEBUG: Done with reduce process for this meshPiece.\n");
}