Can someone explain this behavior to me. I am generating a mesh around my player at run time. I was transforming the world positions to local space with the players transformation because mesh verts are supposed to be locally defined. Then I was passing this mesh along with my players transform to a script on an orthographic camera that looks straight down at the player. The player is right in the center of this cameras view. I am using this mesh to do create a mask.
I use a commandbuffer to render the mesh. To do so I was using the commandbuffer.Drawmesh() method passing in the mesh, the player transforms localToWorldMatrix and the material to use. But the mesh was not getting rotated and the position was all wrong. After trying a few things I got it to work by assigning my mesh verts in worldspace and passing an identity matrix in as the matrix parameter. Is this the right use of this function? It seems super backwards. I assumed the matrix was for the localToWorld, why else have it?
It sounds like you have some issues with your mesh generation, or maybe with how you’re using the transforms elsewhere. Otherwise the transform’s localToWorldMatrix should work fine for any mesh that does not have any scaling from import settings.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class GraphicsDrawMesh : MonoBehaviour
{
public Mesh mesh;
public Material material;
void Update()
{
#if UNITY_EDITOR
if (mesh == null || material == null)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);
if (mesh == null)
mesh = go.GetComponent<MeshFilter>().sharedMesh;
if (material == null)
material = go.GetComponent<MeshRenderer>().sharedMaterial;
DestroyImmediate(go);
}
#endif
Graphics.DrawMesh(mesh, transform.localToWorldMatrix, material, 0, null, 0, null, true, true, true);
}
}
This script should draw a cube, or whatever mesh & material you assign to it, exactly the same as a game object with a MeshRenderer component on it displaying the same mesh & material, as long as it doesn’t have a negative scale.
Though there is a cryptic warning in the documentation about using the transform.localToWorldMatrix for rendering.
Thankfully the Renderer.localToWorldMatrix has some helpful information about why that’s the case.
And by helpful I mean not at all helpful. But the short version is these may be hidden scaling being applied to meshes in certain situations that aren’t documented anywhere. But you shouldn’t have to worry about any of those situations for meshes that are generated from script.
Ultimately though, there’s nothing particularly wrong with just having the mesh be generated in world space and using an identity matrix. This is how all of Unity’s internal mesh batching systems work, like static batching, dynamic batching, UI, and particle systems.
Lol, OK, at least that confirms that I was using the function as it is intended. I am away from my code ATM but I do not think I was setting any shader parameters, at least not on that shader.
It is very strange. If I just render my mesh by assigning it to a mesh filter with verts in local space on a child object it renders exactly the way I would expect it to, same with using gizmos to test the positions. Also drawRenderer worked totally fine with that set up.
But as soon as I switched to just passing the mesh to drawMesh it got all weird. But I guess it is kind of a blessing, as you elude to, because I can skip the calculations of transforming from world to local space in the mesh generation.
Well, besides that one. When I get a chance I will try it with the renderer matrix and local coordinates just for fun.
Edit: Yeah that resulted in no change. If you are interested I could post code to see if you can find anything weird that I am doing, but that isn’t necessary as I got it working with my weird worldSpace mesh, and you are an important person.