How do you manipulate vertices correctly?

Lets say if I need to offset vertices of mesh by Vector3(3.0f, 3.0f, 3.0f), rotate them by 30 degrees in x axis and scale them by Vector3(2f, 2f, 2f), what would be the most efficient way?

I have static class which holds multiple meshes (Loaded from resources), and I need to add them to main mesh and apply to them different positions, rotations and scaling.

This is my solution so far: It looks quite uneffective, and I have no idea how to do rotations.

public static Vector3[] TransformMesh(Mesh mesh, Vector3 position, Quaternion rotation, Vector3 scale)
{
    Vector3[] vertices = mesh.vertices;
    for (int i = 0; i < vertices.Length; i++)
    {
        vertices[i] = Vector3.Scale(vertices[i], scale) + position;
    }
    return vertices;
}

Iā€™m not sure to understand what you are trying to do here.

Do you really have to manipulate mesh vertices, or could you have a GameObject that hold a mesh as one of itā€™s component, giving you the ability to easily manipulate it (rotation, scale, positionā€¦) So you would end up with a hierarchy of gameobject, having each one a meshRenderer.

Or do you really need to have one final mesh (for optimization purpose maybe) ?

ā€œI have static class which holds multiple meshes (Loaded from resources), and I need to add them to main mesh and apply to them different positions, rotations and scaling.ā€

So iā€™m not sure of what is your final goal again, but it makes me think of having something like a terrain, and instanciating objects on it (like rocks or tree) in random position / rotation. If it is the case than you should probably create a bunch of prefab with your different meshes, and manipulate gameObjects.

But again, I donā€™t know what you are trying to achieve so thiis may be totally irrelevant ^^

Assuming you have each mesh as a separate object, I think you could simply apply different position, rotation, and scaling on each object by using the objectā€™s transform. Then, when everything is in place, combine them with the CombineMeshes function.

2 Likes

Its going to be building system and I am very concerned about performance and mainly I hate using monobehaviours for global constants.

Meshes should be avaible to all scenes, and should load at certain time. I am not using gameobjects for this, as I guess I canā€™t instantiate gameobjects on separate thread (So far with my system I can handle 1 mil cubes at once without problems).

Everything works, but I have no clue what to do about rotations.

I figured it out.

        public static Vector3[] TransformMesh(Mesh mesh, Vector3 position, Quaternion rotation, Vector3 scale)
        {
           
            Vector3[] vertices = mesh.vertices;
            Matrix4x4 matrix = Matrix4x4.TRS(position, rotation, scale);
            for (int i = 0; i < vertices.Length; i++)
            {
                vertices[i] = matrix.MultiplyPoint(vertices[i]);
            }
            return vertices;
        }

Have you tested it to prove it is faster than your previous code? I really doubt it because scale + translate is just 3 multiplications and 3 additions, while matrix4x4 multiplication involves 64 multiply ops and 48 adds. You might gain much more performance writing non-allocating version of your code. And more, if youā€™ll just combine those meshes as is and scale+translate your vertices using vertex shader. You may use additional shader channels to pass scale and translation vectors along with vertices.

I did not test it, as I still have no idea how to do rotations without matrix multiplication.

You want to rotate all vertices around the pivot of the mesh? The formula is simple

 x' = x cos Īø āˆ’ y sin Īø

I guess using sin and cos would be less effective than using matrix multiplications? Anyway, I measured matrix multiplication for 1 000 000 vertices, and I guess this will do. Sorry if I was not clear what I was asking for, I basically wanted to find way how to rotate vertex, and if possible, use some fancy function, that is already built into unity.

Sine/cosine are not that hard to compute, see here Computing Trigonometric Functions Moreover, modern cpus and gpus use trigonometric tables to calculate results even faster. And you should know what using Matrix4x4.TRS already includes trigonometric calculations bot sin and cos for all rotation angles. So I think your guess is wrong. Looks like the fastest way it tio combine meshes as they are, send them to the GPU along with transformation data and transform vertices on GPU using simple formulas without matrix multiplication.

1 Like

Oh, I see. You are right, I was somehow thinking that I would need to recalculate trigonometric functions for every vertex, instead I should do it only once for mesh. Thanks for your patience, I will definitively try this.

If you need CPU matrix multiply - set up the matrices before transformation and do your (hopefully parallel) transformations through that matrix on the input vertices / normals. Use Matrix4x4.TRS as commented in earlier posts.

Donā€™t listen to anyone saying ā€œsin and cosā€ arenā€™t expensive. They are pissing in your pocket and telling you itā€™s raining. They are expensive. If you can not use them - donā€™t. Unity has helper functions for this purpose.

If there are enough vertices in the mesh / cluster - use a compute shader - if your platform(s) allow for it. When you are doing generic transformations on data that can be parallelized - consider compute shaders - for almost anything you want to accelerate. You will win.