I'm working on porting a unity project that I made a while ago over to Godot.
In Unity I have a class that looks like this:
public class MeshGenerator
{
public SquareGrid squareGrid;
public MeshFilter walls;
void CreateWallMesh(int[,] map, float squareSize, int tileAmount){
MeshCollider currentColliders = walls.gameObject.GetComponent<MeshCollider>();
Destroy(currentColliders);
CalculateMeshOutlines();
List<Vector3> wallVertices = new List<Vector3>();
List<int> wallTriangles = new List<int>();
Mesh wallMesh = new Mesh();
float wallHeight = 5;
foreach(List<int> outline in outlines){
for(int i = 0; i < outline.Count-1; i++){
int startIndex = wallVertices.Count;
wallVertices.Add(vertices[outline[i]]); // left vertex
wallVertices.Add(vertices[outline[i+1]]); // right vertex
wallVertices.Add(vertices[outline[i]] - Vector3.up * wallHeight); // bottom left vertex
wallVertices.Add(vertices[outline[i+1]] - Vector3.up * wallHeight); // bottom right vertex
wallTriangles.Add(startIndex + 0);
wallTriangles.Add(startIndex + 2);
wallTriangles.Add(startIndex + 3);
wallTriangles.Add(startIndex + 3);
wallTriangles.Add(startIndex + 1);
wallTriangles.Add(startIndex + 0);
}
}
wallMesh.vertices = wallVertices.ToArray();
wallMesh.triangles = wallTriangles.ToArray();
MeshCollider wallCollider = walls.gameObject.AddComponent<MeshCollider>();
wallCollider.sharedMesh = wallMesh;
float textureScale = walls.gameObject.GetComponentInChildren<MeshRenderer> ().material.mainTextureScale.x;
float increment = (textureScale / map.GetLength(0));
Vector2[] uvs = new Vector2[wallMesh.vertices.Length];
float[] uvEntries = new float[]{0.5f,increment};
for (int i = 0; i < wallMesh.vertices.Length; i++)
{
float percentY = Mathf.InverseLerp ((-wallHeight) * squareSize, 0, wallMesh.vertices [i].y) * tileAmount * (wallHeight / map.GetLength(0));
uvs [i] = new Vector2(uvEntries[i % 2],percentY);
}
wallMesh.uv = uvs;
wallCollider.sharedMesh = wallMesh;
walls.mesh = wallMesh;
}
And I'm getting an error that says
The type or namespace name 'MeshFilter' could not be found (are you missing a using directive or an assembly reference?)
I believe it's referencing this unity mesh, and I'm curious what the correct way to do it in Godot is.
Edit:
In case it helps, what the class does is takes a random 2D map and builds up walls around the area the player is supposed to travel through. Here's a sample:
For creating a Mesh
in runtime in Godot see ImmediateMesh
, MeshDataTool
or SurfaceTool
. With any of those you can get a Mesh
that you can display using a MeshInstance3D
or for other uses.
Although ImmediateMesh
name and interface evoke the old OpenGL immediate mode, it is only an usability façade.
The code suggest you also want a collider. That means you want a Shape3D
that you can use with a CollisionShape3D
child of an Area3D
, StaicBody3D
, CharacterBody3D
, RigidBody3D
... Note: they can have multiple CollisionShape3D
or CollisionPolygon3D
children, so you do not need to make a single collider.
The Shape3D
can be one of the many primitive shapes (e.g. BoxShape3D
), which are the most performant.
Alternatively you can pick between ConcavePolygonShape3D
and ConvexPolygonShape3D
. You can create them from a Mesh
using create_trimesh_shape
and create_convex_shape
respectively.
ConcavePolygonShape3D
is THE WORSE. You have been warned.
See also create_convex_collision
, create_multiple_convex_collisions
and create_trimesh_collision
from MeshInstance3D
. In particular create_multiple_convex_collisions
will do decomposition for you.
Be aware that these method will create StaticBody3D
children of the MeshInstance3D
. If you do not want StaticBody3D
, you can always take the colliders, remove them from their parent, and add them where you need them.
Addendum
After looking at the picture, I believe using CSG nodes this would be easy for you.
CSG stands for Constructive Solid Geometry, it is making boolean operations with 3D shapes.
So you can have a CSGCombiner3D
with a child CSGBox3D
for the exterior volume. And then to substract a CSGPolygon3D
from it, you add it as second child and set its operation
to OPERATION_SUBTRACTION
.
To define the CSGPolygon3D
all you need is to figure out the polygon in 2D since it extends it to 3D using a depth
you can configure.
Once you have it setup, you can use get_meshes
which gives you an array with a Transform3D
and a Mesh
(which you can use in a MeshInstance3D
, from which you can also generate a physics body as explained above).
Or, alternatively, you can use the CSG nodes directly. Since you can set use_collision
to true
to enable physics.