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