EditableMesh normals/UVs not being calculated properly

Hello everyone!
Since I’m not the best at dealing with normals & UVs and I wasn’t able to find a solution on my own, I thought I’d ask you guys.

In short, I’ve got a system going which fractures glass into multiple shards from a point. It seems to be working great, other than the fact that on the front side two shards stick out because they appear to be shaded smoothly toward a darker tone in one corner. That is visible in this image:

And the back side has seemingly got every shard shaded smoothly…
image

The above is the result when resetting the normals with this code:

local normalIds = editableMesh:GetNormals()
for i = 1, #normalIds do
	editableMesh:ResetNormal(normalIds[i])
end

If I don’t reset the normals, the result is this (on the front):
image

And like this on the back
image

Seems like all the faces are split into differently colored triangles on the back if I don’t reset the normals.

Though I doubt that the problem is in the code that makes the shards, I’ll provide it anyway.
The code to build every shard works the same, given that the vertices are already provided. An important thing to note for the algorithm to work tho, is that all the vertices are ordered clockwise and all of the polygons are convex.
Essentially, for every vertex starting from the third one, it makes a triangle with the i-th, i-1 -th and the 1st vertex, covering the entire polygon that it received as input that way. Then, it “extrudes” every vertex that it already made for the polygon to make the polygon a 3D shard and simultaneously makes triangles for the edges of the shard.
I hope the code is commented well enough.

-- For people trying to read this mess, for memory optimization purposes,
-- I need to use pre-made meshparts that have the exact amount of vertices and triangles in place already.
editableMesh = AssetService:CreateEditableMeshAsync((presetPolys["Poly"..tostring(#poly)]).MeshContent, { FixedSize = true } :: {[string]: any})

local pointsSum: Vector2 = Vector2.zero -- The sum of all the positions of the vertices

local vertIndices: {number} = editableMesh:GetVertices()
local faces: {number} = editableMesh:GetFaces()
local faceIdx: number = 1

-- Sum up all the vertices and add triangles
for i: number = 1, n do
	local point: Vector2 = poly[i]
	pointsSum += point

	-- If we have assigned enough vertices, make triangles with the first, second and i-th vertex to fill the poly
	if i > 2 then
		editableMesh:SetFaceVertices(faces[faceIdx], {vertIndices[1], vertIndices[i-1], vertIndices[i]})
		faceIdx += 1
	end
end
local pointsArithmeticCenter: Vector2 = pointsSum/#poly -- The arithmetic center of all the vertex positions

-- Set the position of the shard to be at the arithmeic center of all the vertices
shardCF = relativeTo + relativeTo.RightVector * pointsArithmeticCenter.X + relativeTo.UpVector * pointsArithmeticCenter.Y

-- Set the positions of all the vertices, taking into account the new position of the glass shard
for i: number = 1, n do
	local point: Vector2 = poly[i]
	local sub: Vector2 = point - pointsArithmeticCenter
	table.insert(vertices, sub)
	editableMesh:SetPosition(vertIndices[i], Vector3.new(sub.X, sub.Y, relativeToData.Thickness/2))
end

-- Add the vertices and triangles for the second side of the glass shard and for the edges
for i: number = n+1, n*2 do
	editableMesh:SetPosition(vertIndices[i], editableMesh:GetPosition(vertIndices[i-n]) - Vector3.new(0, 0, relativeToData.Thickness))

	-- If we have assigned enough vertices, make triangles with the n+1, n+2 and the i-th vertex to fill the second side of the glass shard
	if i > n+2 then
		editableMesh:SetFaceVertices(faces[faceIdx], {vertIndices[i], vertIndices[i-1], vertIndices[n+1]})
		faceIdx += 1
	end

	-- If we have enough vertices on both sides to start making triangles for the edges, then we do so
	if i > n+1 then
		editableMesh:SetFaceVertices(faces[faceIdx], {vertIndices[i-1], vertIndices[i], vertIndices[i-n]})
		editableMesh:SetFaceVertices(faces[faceIdx+1], {vertIndices[i-n], vertIndices[i-n-1], vertIndices[i-1]})
		faceIdx += 2

		-- Since we couldn't make triangles for the first vertex when we assigned it, because the i-th one was missing, we make them now that we have the i-th one
		if i == n*2 then
			editableMesh:SetFaceVertices(faces[faceIdx], {vertIndices[n*2], vertIndices[n+1], vertIndices[1]})
			editableMesh:SetFaceVertices(faces[faceIdx+1], {vertIndices[1], vertIndices[n], vertIndices[n*2]})
			faceIdx += 2
		end
	end
end

I’m fairly certain, that the code is correct and winds all the triangles correctly so that they wouldn’t be facing the wrong way. Although, I have noticed that the two shards that have that one tinted vertex are the only ones with 7 vertices on both sides. All the other ones have less. Given that calling ResetNormal on all the normals still kept those two like that, I’m not sure what to do really. And the back seems to be a whole nother story.

1 Like

I’ve never dealt with EditableMesh before. Are you using a regular part? Or is it an actual MeshPart?

If you’re using blender, Select Object → Right Click → Shade Flat

The shards are made with meshparts that have the editable mesh applied to them

What does it look like before shatter?

There essentially isnt anything before shatter. Just this normal part
image

So, it’s a normal part and then you sneakily replace it with broken glass?

Yep. Something along the lines of that

So, couldn’t you just swap it out with ‘pre-broken’ glass?

Forgot to mention, the broken glass looks nice.

2 Likes

The system supports breaking glass of basically all shapes. I can’t just bake it all. Sure, I could make some on startup, but that wouldn’t fix the issue of the shading.

Sorry, but I don’t really understand EditableMeshes. Hope you find the answer though!

Can’t you only have like 5 EditableMeshes in game? I think a better approach would be to just have a broken glass pane to begin with. I’m assuming you want the glass to shatter exactly where it’s hit, but I don’t think it would make much of a difference visually.

But if you really need to, you can use :SetUV().

How many different kinds of shapes do you need to break?

Different shaped of glass.
chars

You can have far more than 5 if you use FixedSize editable meshes btw. i can’t have any whole pane pre-broken. Every glass pane and all the shards that are generated can all be broken, no matter where you shatter the glass from. This requires flexibility.

Maybe, but my problem is about how. If that would fix the problem, it’d be nice, but I tried it without avail. If you know how SetUV could be used, I’d be glad to hear it. Though I’m confused as to how the problem could be with the UVs, since no textures are being used.

Like what? List all the shapes you have right now. If it’s like 10, you can just pre-break them. There’s a Blender plugin for that.

First you do :AddUV(), and then use :SetUV() for every vertex. The specifics you’ll have to figure out for yourself. But basically, UVs work just like in Blender. If you don’t know, then look it up online. You set a coordinate on a texture, and then the vertices get rendered onto that texture.

Even if there were that few, you can still break the glass from different points, each of which will interact with the edges of the glass differently. And the pattern that is used for breaking will be rotated for variety, making baking all that pretty much impossible.
The main point is that even if there aren’t many different glass panes to begin with, each shard that the glass gets broken into can be broken once again, those shards that get generated from breaking the shard can be broken again etc. Essentially an infinite amount of different polygons can emerge from doing so, so in no world can that be baked. And there are many different sizes of rectangular panes.

Yeah, I understand how UVs work, but applying them for this usecase is the thing I don’t understand. UVs shouldn’t (correct me if I’m wrong) have anything to do with the black tint at the corners of those two shards, since there are no textures being applied. And what about the back? It’s just completely off. I suspect that it has to do something with normals, since changing them changes the look a bit, but how exactly to change them I don’t know.

It doesn’t have to be this complex. What are you making where it’s important how the glass shatters in Roblox?

It does. What I’m making is glass shattering. That’s the point.

Also, an update, turning cast shadow off on the parts almost fixed the bug, however the tint still happens at the front. the back looks a lot better tho. You can still see a lot of artifacts tho

1 Like

Very nice project by the way
Charsss

1 Like