MelonLoader

MelonLoader

554 Downloads

Can I register a custom struct to create an il2cpp type?

JamieDavidson opened this issue ยท 1 comments

commented

All of the following criteria must be met

  • All Requirements must be installed.
  • Changed the title so that it doesn't just says "[Bug]: "
  • I have searched the GitHub issues for my bug, even in the closed issues.

All of the following are optional to answer

  • Tried reinstalling the Game.
  • Tried reinstalling MelonLoader.
  • Tried restarting PC.
  • Was able to see the Start Screen.

Describe the issue.

Melonloader version 0.6.6
Engine version 2022.3.51f1

I'm trying to dump mesh data from a mesh that has had isReadable set to false, and therefore doesn't have vertex data in CPU addressable memory anymore. I've had some success with reading vertex data from the vertex buffer:

var meshCollider = hit.transform.GetComponent<MeshCollider>();
var sharedMesh = meshCollider.sharedMesh;

var vertexBuffer = sharedMesh.GetVertexBuffer(0);
var vertexCount = sharedMesh.vertexCount;

var vertices = Array.CreateInstance(Il2CppType.Of<Vector3>(), vertexCount);
vertexBuffer.GetData(vertices);

foreach (var vertex in vertices)
{
    var vec = vertex.Unbox<Vector3>();
    // Do other processing bits that work fine
}

This works fine, as long as the Stride for the buffer is only 12 bytes (i.e., the vertex buffer has a single Vector3 position attribute descriptor), but other meshes have e.g., 56 byte strides, containing position, normal etc.

I've defined a custom struct with the same layout described by the attributes of the vertex buffer I'm trying to dump

[StructLayout(LayoutKind.Sequential)]
public struct MeshStride56
{
    public Vector3 Position;
    public Vector3 Normal;
    public Vector4 Tangent;
    public Vector2 TexCoord0;
    public Vector2 TexCoord1;
}

But trying to create an array with var vertices = Array.CreateInstance(Il2CppType.Of<MeshStride56>(), vertexCount); results in an exception because the il2cpp type is missing. I can't figure out how to register

If I make MeshStride56 a class, and inherit from il2cpp object I can no longer use Unbox.

I've tried using a call to InternalGetData, hoping that it would read in 56 byte blocks and map the first 12 to the Vector3 (as Position is always the first attribute) like so, but this results in mangled data:

var vertexBuffer = sharedMesh.GetVertexBuffer(0);
var vertexCount = sharedMesh.vertexCount;
var totalStride = sharedMesh.GetVertexBufferStride(0);

var vertices = Array.CreateInstance(Il2CppType.Of<Vector3>(), vertexCount);

vertexBuffer.InternalGetData(vertices, 0, 0, vertexCount, totalStride);

Can I register my custom struct for use with Il2CppType.Of? Is there some alternative to Unboxing that I can do with a class? I couldn't find much online. Thanks in advance.

Did you attach your log file?

No, I could not find a log file at {Game_Directory}\MelonLoader\Latest.log

commented

You can easily work around this by using GetNativeBufferPtr.

In an unsafe context, you can get the array like this:

var vertices = (MeshStride56*)vertexBuffer.GetNativeBufferPtr();

From there, you can use the pointer like a normal array:

Logger.Msg(vertices[1].Position.x.ToString());

You can use vertexBuffer.count to get the length of the array.