# How to distribute meshes within triangle face bounds?

Attention Topic was automatically imported from the old Question2Answer platform.

My goal is to distribute grass mesh instances on a terrain mesh, created in Blender, using MultiMeshInstance.
Script gets all the triangles of a terrain mesh through MeshDataTool and places a MultiMeshInstance for each triangle. How to evenly distribute meshes inside a given triangle with respect to height and a normal direction of a triangle?
I have these 3 points, from documentation.

``````for i in mesh_data_tool.get_face_count():

# Get the index in the vertex array.
var a = mesh_data_tool.get_face_vertex(i, 0)
var b = mesh_data_tool.get_face_vertex(i, 1)
var c = mesh_data_tool.get_face_vertex(i, 2)

# Get vertex position using vertex index.
var ap = mesh_data_tool.get_vertex(a)
var bp = mesh_data_tool.get_vertex(b)
var cp = mesh_data_tool.get_vertex(c)
``````

I set the instance’s transform, like this:

``````	#Random scale and rotation
var t = Transform().scaled(Vector3(rand_scale, rand_scale, rand_scale)).rotated(Vector3.UP, randf() * TAU)

# This gives a point within a rectangle
# Actually this doesn't work
var rand_x = randf() * ap.length()
var rand_z = randf() * bp.length()

# Setting the transform
t.origin = Vector3(rand_x, 0, rand_z)
mm.set_instance_transform(i, t)
``````

Why I don’t use Populate Surface, because this way I can hide multi meshes on triangles which player can’t see.

So I was trying to solve the exact same problem and also limit mesh instances based on vertex color.

I ended up looking into the Populate function used in the editor to get some ideas.

I noticed that it uses a function on line 190 `Vector3 pos = face.get_random_point_inside();`

Unfortunately the face3 math library isn’t exposed as far as I am aware. But looking in https://github.com/godotengine/godot/blob/07025e607dda2ab3b35bee65614347dc39f6f236/core/math/face3.cpp

We can find the function on line 153.

Using your bit of code I was able to figure it all out.

``````func get_valid_verts():
for i in mdt.get_face_count():
# Get the index in the vertex array.
var a = mdt.get_face_vertex(i, 0)
var b = mdt.get_face_vertex(i, 1)
var c = mdt.get_face_vertex(i, 2)
# Get vertex position using vertex index.
var ap = mdt.get_vertex(a)
var bp = mdt.get_vertex(b)
var cp = mdt.get_vertex(c)
if mdt.get_vertex_color(a).r > 0.1:
verts.append({"verts":[ap,bp,cp],"vertcol":mdt.get_vertex_color(a)})
``````

So here for my approach I get all the face verts, but at the end I filter out those whose vertex colour is less than 0.1. This allows one to paint vertex colours in Blender for example or potentially also make use of the VPainter tool I imagine.

``````func get_random_point_inside(vertices) -> Vector3:
var a
var b
a = rand_range(0.0,1.0)
b = rand_range(0.0,1.0)
return vertices[0] * a + vertices[1] * (b - a) + vertices[2] * (1.0 - b)
``````

Rewrote the Face3 function to return a random point given a set of 3 vertices.

``````func addGrass(a):
get_valid_verts()
multimesh.multimesh.instance_count = 5000
for i in multimesh.multimesh.instance_count:
var xform = Transform()
verts.shuffle()
var randpos = get_random_point_inside(verts[0].verts)
var pos = global_transform.xform(randpos)
#print(pos)
var basis_scale = Vector3(verts[0].vertcol.r,verts[0].vertcol.g,verts[0].vertcol.b)
multimesh.multimesh.set_instance_custom_data(i,Color(
basis_scale.x,
basis_scale.y,
basis_scale.z
))
xform.origin = pos
xform.basis = basis
multimesh.multimesh.set_instance_transform(i,xform)
``````

Put it all together.

Sorry code is a bit of a mess as I was tinkering to get this to work. Hope this helps.

Just noticed there is a slight issue with the height as some are floating. Think this might be because they aren’t being aligned to the normal of the face.

Defaultsound | 2020-09-19 14:42

Figured out the floating instances. Turns out the “swap” is fairly important to ensure that the point is within the range of the triangle. I also flipped the test to be less than rather than greater than, so that was also causing issues.

As Godot doesn’t have a swap function, I came up with this:

``````func get_random_point_inside(vertices,amount) -> Vector3:
var a
var b
a = rand_range(0.0,amount)
b = rand_range(0.0,amount)
if  a > b:
var x
var y
x = a
y = b
b = x
a = y
return vertices[0] * a + vertices[1] * (b - a) + vertices[2] * (1.0 - b)
``````

Defaultsound | 2020-09-20 12:43

This is cool! Sorry for the late reply.

wowzzers | 2020-12-02 19:52