Rendering Bug: ExtentsCFrame offset applied twice when frustum culling

This might be an editable mesh-specific bug.

When frustum culling, the extents offset cframe (computed as Part.CFrame:Inverse() * Part.ExtentsCFrame) is applied twice, causing the mesh to sometime be un-rendered when should be rendered.

reproduction:
Run the following code in the Command bar.

local AssetService = game:GetService("AssetService")


-- Given 4 vertex IDs, adds a new normal and 2 triangles, making a sharp quad

local function addSharpQuad(eMesh, vid0, vid1, vid2, vid3)
	local nid = eMesh:AddNormal()  -- This creates a normal ID which is automatically computed
	local fid1 = eMesh:AddTriangle(vid0, vid1, vid2)
	eMesh:SetFaceNormals(fid1, {nid, nid, nid})
	local fid2 = eMesh:AddTriangle(vid0, vid2, vid3)
	eMesh:SetFaceNormals(fid2, {nid, nid, nid})
end


-- Makes a cube with creased edges between the 6 sides

local function makeSharpCube()
	local eMesh = AssetService:CreateEditableMesh()
	local v1 = eMesh:AddVertex(Vector3.new(-1, -1, -1))
	local v2 = eMesh:AddVertex(Vector3.new( 1, -1, -1))
	local v3 = eMesh:AddVertex(Vector3.new(-1,  1, -1))
	local v4 = eMesh:AddVertex(Vector3.new( 1,  1, -1))
	local v5 = eMesh:AddVertex(Vector3.new(-1, -1,  1))
	local v6 = eMesh:AddVertex(Vector3.new( 1, -1,  1))
	local v7 = eMesh:AddVertex(Vector3.new(-1,  1,  1))
	local v8 = eMesh:AddVertex(Vector3.new( 1,  1,  1))
	addSharpQuad(eMesh, v5, v6, v8, v7)  -- Front
	addSharpQuad(eMesh, v1, v3, v4, v2)  -- Back
	addSharpQuad(eMesh, v1, v5, v7, v3)  -- Left
	addSharpQuad(eMesh, v2, v4, v8, v6)  -- Right
	addSharpQuad(eMesh, v1, v2, v6, v5)  -- Bottom
	addSharpQuad(eMesh, v3, v7, v8, v4)  -- Top
	eMesh:RemoveUnused()
	return eMesh
end


local function applyOffset(eMesh, offset)
	for _, vert in eMesh:GetVertices() do
		eMesh:SetPosition(vert, eMesh:GetPosition(vert) + offset)
	end
end

-- apply offset before. This does not work well, ExtentsCFrame offset is nonidentity
local eMesh0 = makeSharpCube()
applyOffset(eMesh0, Vector3.new(10, 0, 0))
local part0 = AssetService:CreateMeshPartAsync(Content.fromObject(eMesh0))
part0.Anchored = true
part0.Name = "NonidentityExtents"
part0.CFrame = CFrame.new(0, 3, 0)
part0.Parent = workspace
part0.Color = Color3.new(0, 1, 0)

-- apply offset afterwards. This works fine, ExtentsCFrame offset is identity
local eMesh1 = makeSharpCube()
local part1 = AssetService:CreateMeshPartAsync(Content.fromObject(eMesh1))
applyOffset(eMesh1, Vector3.new(10, 0, 0))
part1.Anchored = true
part1.Name = "IdentityExtents"
part1.CFrame = CFrame.new(0, 1, 0)
part1.Parent = workspace
6 Likes

Thanks for the report! We’ll follow up when we have an update for you.

2 Likes