C# - How do I copy the Mesh texture to a new Mesh?

I’m modifying the topology of a mesh which has a picture mapped to it (decal) using Grasshopper.

In the GH component I first make a copy of the mesh, but I just can’t find a way to copy also the texture to make the new mesh a full copy. How is that done in C#?

The mesh I copied like so:

var newMesh = oldMesh.DuplicateMesh();

// Now, how to copy also the texture?

//Rolf

Ping, any texture experts out there?

You will likely need to copy the material to the new object. Without an example file, here is a guess and maybe a hint ObjectAttributes.MaterialIndex property

Yes, I was asking about how to do the copying. Here’s an example file:

R8 - 3D-Terrain - Forum Example.3dm (3.2 MB)

R8 - 3D-Terrain - Forum Example.gh (5.4 KB)

//Rolf

Grok put me on track…

This is how I finally coded the copying of the Decal to a Mesh copy.

First I copied the mesh, and sent both the original and the copy to the following method, which duplicated and returned the original Decal for later insertion into the mesh copy:

	var mesh = M.DuplicateMesh();

	if(!GetDecalCopyFromMesh(M, mesh, out mesh, out Decal newDecal, out Guid copyId))
	{
	     PrintError(“Error - Copying Mesh Texture failed.”);
	     return;
	} 

	// Creates a Decal from the original mesh and returns the id (Guid) of the pre-created mesh copy.
	// The decal is not applied here directly, since it requires Baking the copy, which is left to
	// the caller to do decide later. If baking, the decal is then applied to the copy after it
	// has been added to Rhino Document (this is not always a given, if the calling code is aborted
	// for so reason)
	//
	private bool GetDecalCopyFromMesh(Mesh originalMesh, Mesh meshCopy, out Mesh texturedMesh, out Decal newDecal, out Guid copyId)
	{
	// --------------------------------------------------
	// initialize out-params in case aborting prematurely
	// --------------------------------------------------

    texturedMesh = null;
    newDecal = null;
    copyId = Guid.Empty;

    // --------------------------------------------------
    // Retrieve the original mesh (must already exist in 
    // the Rhino doc in order to access its object and decals)
    // --------------------------------------------------

    //Guid originalId = RhinoDoc.ActiveDoc.Objects.AddMesh(originalMesh);
    if (!FindObjectGuidForMesh(originalMesh, out Guid originalId))
    {
        PrintError("The input (original) Mesh doesn't seem to exist in the Rhino Document");
        return false;
    }
    RhinoObject originalObj = RhinoDoc.ActiveDoc.Objects.FindId(originalId);
    if (originalObj == null) 
    {
        PrintError("The input (original) Mesh doesn't seem to exist as a RhinoObject (Mesh)");
        return false;
    }

    // --------------------------------------------------
    // Get decals from the original object
    // --------------------------------------------------

    var decals = originalObj.Attributes.Decals;
    if (decals.Count() == 0)
    {
        PrintError("No decals found on the original mesh.");
        return false;
    }

    // --------------------------------------------------
    // Duplicate the geometry (ensure it's a clean copy)
    // --------------------------------------------------

    Mesh copy_mesh = meshCopy.DuplicateMesh();

    // ----------------------------------------------
    // Copy decal data
    // ----------------------------------------------

    foreach (Rhino.Render.Decal decal in decals)
    {
        // Create a new decal instance with the same properties
        var decal_params = new  Rhino.Render.DecalCreateParams();

            decal_params.DecalMapping = decal.Mapping;
            decal_params.DecalProjection = decal.Projection;
            decal_params.EndLatitude = decal.EndLatitude;
            decal_params.EndLongitude = decal.EndLongitude;
            decal_params.Height = decal.Height;
            decal_params.MapToInside = decal.MapToInside;
            decal_params.MaxU = 1.0; //decal.MaxU;
            decal_params.MaxV = 1.0; //decal.MaxV;
            decal_params.MinU = 0.0; //decal.MinU;
            decal_params.MinV = 0.0; //decal.MinV;
            decal_params.Origin = decal.Origin;
            decal_params.Radius = decal.Radius;
            decal_params.StartLatitude = decal.StartLatitude;
            decal_params.StartLongitude = decal.StartLongitude;
            decal_params.TextureInstanceId = decal.TextureInstanceId;
            decal_params.Transparency = decal.Transparency;
            decal_params.VectorAcross = decal.VectorAcross;
            decal_params.VectorUp = decal.VectorUp;

        newDecal = Decal.Create(decal_params);
        if (newDecal == null)
        {
            PrintError("Failed to create decal copy.");
            return false;
        }
    }       

    texturedMesh = copy_mesh;
    return true;
}

Then, when (if) the manipulation of the mesh copy was accepted, the Mesh was Baked and the Decal copy applied to it, like so:


    // Bakes a mesh to the Rhino Document. Applies a (prepared) Decal Texture to 
    // the  mesh and places the Mesh on a dedicated Layer ("toLayer")
    //
    private Guid BakeMesh(Mesh newMesh, Decal decal, string toLayer)
    {
        // Ensure that a target Layer actually exists
        const int notFoundValue = -1;
        var toLayerIndex = RhinoDoc.ActiveDoc.Layers.FindByFullPath(toLayer, -1);
        if (toLayerIndex == notFoundValue)
        {
            PrintError("The target Layer doesn't exist in the Rhino Document");
            return Guid.Empty;
        }

        ObjectAttributes attrs = new ObjectAttributes();
        if (decal != null)
        {
            attrs.LayerIndex = toLayerIndex;
            attrs.Decals.Add(decal);
            // newMesh.Attributes.Decals.Add(newDecal);
        }

        // Bake
        var guid = RhinoDoc.ActiveDoc.Objects.AddMesh(newMesh, attrs);

        // Find the baked instance reference inside the Rhino document.
        var meshObj = RhinoDoc.ActiveDoc.Objects.FindId(guid);
        meshObj.CommitChanges();

        // Update display
        RhinoDoc.ActiveDoc.Views.Redraw();
        return guid;
    }

Edit: Corrected a (copied) comments to mention “Layer”, not Mesh, etc.