Plane doesn’t render.
editablemesh_plane.rbxl (53.2 KB)
run a for loop in a smaller res than the image, scale these iterations proportionately along the image, get the color data for those pixels, and make a new image that draws clusters of pixels that represent each downscaled pixel
problem solved
this is because all vertices’ Y positions are the same. It’s been a bug for a bit now.
You can fix it by making sure they’re not all on the same Y position like this
local v1 = eMesh:AddVertex(Vector3.new(-5, 0, -5))
local v2 = eMesh:AddVertex(Vector3.new(5, 1, -5)) --> change it to something that's not also 0
local v3 = eMesh:AddVertex(Vector3.new(-5, 0, 5))
local v4 = eMesh:AddVertex(Vector3.new(5, 0, 5))
Thanks for sharing! Both are fixed and will be updated soon!
I’m enabling a change to log a warning each time EditableMesh:CreateMeshPartAsync is called:
EditableMesh:CreateMeshPartAsync is deprecated and will be removed in the next release. Use AssetService:CreateMeshPartAsync instead.
Planning to disable EditableMesh:CreateMeshPartAsync
a week from now, next Wednesday.
My studio client is crashing when pressing the stop button during a play solo test when using EditableImage.
Here’s a repro place:
bugTest.rbxl (55.5 KB)
Log file:
0.650.0.6500743_20241107T083141Z_Studio_EFD72_last.log (502.6 KB)
Simply just run a solo test, maybe walk around for a couple seconds, and then press stop, and it will freeze the client for a few seconds and then close the window.
Can we get a simple, toned down script examples in the hub for each of the API. Just trying to create a simple mesh is super confused? The way it’s worded, this
local AssetService = game:GetService("AssetService")
local EditableMesh = AssetService:CreateEditableMesh()
local MeshPart = AssetService:CreateMeshPartAsync(EditableMesh) -- ?
CreateMeshPartAsync sounds like it creates a MeshPart, but I get unable to cast Object to Content? First sentence
To me implies that the EditableMesh is what I put inside the CreateMeshPartAsync?
And even example code provided is confusing
To me, I’d imagine I should be able to just copy/paste from the hub and press play and it’d work, but the function never gets called and I have no clue how to actually attribute the EditableMesh to a mesh part
See, I read the hub as this? Like what is MeshContent?
AssetService:CreateMeshPartAsync(makeSharpCube())
Like can anyone just provide simple code for creating a flat plane, or a cube. That I can copy/paste into studio and play and have it work right there? Cause nothing here is working in studio for me and I can’t figure it out myself
local AssetService = game:GetService("AssetService")
local myMeshPart = workspace:FindFirstChildWhichIsA("MeshPart")
local myEditableMesh = AssetService:CreateEditableMesh()
local v1 = myEditableMesh:AddVertex(Vector3.new(0, 0, 0))
local v2 = myEditableMesh:AddVertex(Vector3.new(1, 0, 0))
local v3 = myEditableMesh:AddVertex(Vector3.new(0, 1, 0))
local v4 = myEditableMesh:AddVertex(Vector3.new(1, 1, 0))
local v5 = myEditableMesh:AddVertex(Vector3.new(0, 0, 1))
local v6 = myEditableMesh:AddVertex(Vector3.new(1, 0, 1))
local v7 = myEditableMesh:AddVertex(Vector3.new(0, 1, 1))
local v8 = myEditableMesh:AddVertex(Vector3.new(1, 1, 1))
-- Helper method to compute extents of a Mesh. This will eventually
-- be replaced with a direct getter method on EditableMesh
local function computeExtents(em: EditableMesh)
local verts = em:GetVertices()
if #verts == 0 then
return Vector3.zero
end
local inf = math.huge
local min = Vector3.new(inf, inf, inf)
local max = Vector3.new(-inf, -inf, -inf)
for _, id in verts do
local v = em:GetPosition(id)
min = min:Min(v)
max = max:Max(v)
end
return max - min
end
-- Create a new MeshPart instance linked to this EditableMesh Content
-- Note: EditableMesh:CreateMeshPartAsync will be replaced with
-- AssetService:CreateMeshPartAsync(Content, …) before public release
local newMeshPart = myEditableMesh:CreateMeshPartAsync(computeExtents(myEditableMesh))
-- Apply newMeshPart which is linked to the EditableMesh onto myMeshPart
myMeshPart:ApplyMesh(newMeshPart)
-- Any changes to myEditableMesh will now live update on myMeshPart
local vertexId = myEditableMesh:GetVertices()[1]
myEditableMesh:SetPosition(vertexId, Vector3.one)
-- You can create more MeshPart instances that reference the same
-- EditableMesh content
local newMeshPart2 = myEditableMesh:CreateMeshPartAsync(computeExtents(myEditableMesh))
-- Drop newMeshPart2 under workspace to render it
newMeshPart2.parent = workspace
-- Any changes to myEditableMesh will now live update on both
-- myMeshPart and newMeshPart2
myEditableMesh:SetPosition(vertexId, Vector3.one*2)
-- Calling these two lines again will recalculate collision and fluid geometry
-- with a snapshot of the current edits and update myMeshPart.
-- It is generally recommended to do this at the end of a conceptual edit operation.
-- Note: EditableMesh:CreateMeshPartAsync will be replaced with
-- AssetService:CreateMeshPartAsync(Content, …) before public release
local newMeshPart = myEditableMesh:CreateMeshPartAsync(computeExtents(myEditableMesh))
myMeshPart:ApplyMesh(newMeshPart)
Invalid mesh. Cannot create a MeshPart from an empty mesh. Mesh has no faces. - Server - Script:35
like what am I doing wrong… it has faces, I create vertices, thus it should have faces??
EditableMesh
is of type Object
but AssetService:CreateMeshPartAsync
takes in a Content
. so all you need to do is to convert your EditableMesh
using Content.fromObject()
like this:
local MeshPart = AssetService:CreateMeshPartAsync(Content.fromObject(EditableMesh))
Take a read through this section on Content
for more info and background.
Remember that your EditableMesh
cannot be empty (i.e. it needs to have valid vertices and faces before it can be converted into a MeshPart
)
You seem to already have the code to create vertices, but you are missing the code to group those vertices into valid triangles using local faceId = myEditableMesh:AddTriangle(v1, v2, v3)
.
Take a look at the second code snippet to create a sharp cube here. You will notice that the addSharpQuad()
function adds two triangles and a new normal given four vertices:
-- Given 4 vertex ids, adds a new normal and 2 triangles, making a sharp quad
local function addSharpQuad(emesh, vid0, vid1, vid2, vid3)
-- AddTriangle creates a merged normal per vertex by default.
-- For the sharp cube, we override the default normals with
-- 6 normals - a new normal to use for each side of the cube
local nid = emesh:AddNormal()
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
It would be nice to be able to load Roblox-generated images like avatar thumbnails.
For example, rbxthumb://type=Avatar&id=1084073&w=352&h=352
which was generated by the method Players:GetUserThumbnailAsync()
This seems pretty fair-game to me. Thanks for consideration.
Thanks for your report, we should have a fix for this issue coming out very soon. There is a bug that causes a crash if EditableImage or EditableMesh are deconstructed during DataModel shutdown.
There a huge issue where a mesh generated when I play test server, it generates correctly, but when I play solo it is messed up?
local WALL_THICKNESS = 0.8
local WALL_HEIGHT = 14
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()
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
-- Creates a wall mesh between two points
local function makeWallBetweenPoints(startPos, endPos)
local eMesh = AssetService:CreateEditableMesh()
-- Calculate wall direction and length
local wallVector = endPos - startPos
local wallLength = wallVector.Magnitude
-- Calculate rotation angle around Y axis
local angle = math.atan2(wallVector.X, wallVector.Z)
local cs = math.cos(angle)
local sn = math.sin(angle)
-- Function to rotate a point around Y axis
local function rotatePoint(x, y, z)
local rotatedX = x * cs - z * sn
local rotatedZ = x * sn + z * cs
return Vector3.new(
rotatedX + startPos.X,
y + startPos.Y,
rotatedZ + startPos.Z
)
end
-- Create vertices for the wall
local v1 = eMesh:AddVertex(rotatePoint(0, 0, 0))
local v2 = eMesh:AddVertex(rotatePoint(wallLength, 0, 0))
local v3 = eMesh:AddVertex(rotatePoint(0, WALL_HEIGHT, 0))
local v4 = eMesh:AddVertex(rotatePoint(wallLength, WALL_HEIGHT, 0))
local v5 = eMesh:AddVertex(rotatePoint(0, 0, WALL_THICKNESS))
local v6 = eMesh:AddVertex(rotatePoint(wallLength, 0, WALL_THICKNESS))
local v7 = eMesh:AddVertex(rotatePoint(0, WALL_HEIGHT, WALL_THICKNESS))
local v8 = eMesh:AddVertex(rotatePoint(wallLength, WALL_HEIGHT, WALL_THICKNESS))
-- Create the faces
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 createWallBetweenParts(partA, partB)
local startPos = partA.Position
local endPos = partB.Position
local wallMesh = makeWallBetweenPoints(startPos, endPos)
local meshPart = AssetService:CreateMeshPartAsync(Content.fromObject(wallMesh))
meshPart.Parent = workspace
return meshPart
end
local wallMesh = makeWallBetweenPoints(Vector3.new(0, 0, 0), Vector3.new(10, 0, 10))
local meshPart = AssetService:CreateMeshPartAsync(Content.fromObject(wallMesh))
meshPart.Anchored = true
meshPart.Parent = workspace
EDIT Further testing on the above, it seems EditableMeshes only load based on if it server or client script? Can see I render the above code using a server script, and it’s visually there on the server + collisions exist but it does not render on client
Also, there’s an unloading bug
More bugs to report. Unsure if I’m mis-interpreting. But I run this is in RenderStepped. I basically want to visualize the mesh.
-- Example usage:
local Start, End = DragTracker.StartPos, DragTracker.CurrentPos
local wallMesh = makeCurvedWall(Start, End, (End + Start) / 2, 15)
if not meshPart then
meshPart = AssetService:CreateMeshPartAsync(Content.fromObject(wallMesh))
meshPart.Anchored = true
meshPart.CanCollide = false
meshPart.Parent = workspace
else
meshPart:ApplyMesh(AssetService:CreateMeshPartAsync(Content.fromObject(wallMesh)))
end
I obviously don’t want to destroy and recreate a mesh constantly, so was trying to basically just “edit” the EditableMesh and apply it to the mesh. But my studio will crash doing this after a few seconds
Hello good. Help me with something, I’m trying to do a kind of Cel-Shading, but from what I see, you can no longer edit a mesh in real time (and make it visible) because the meshContent method cannot be assigned. Tips? since creating a new mesh is not profitable.
Code:
local mesh = workspace.Head
local obj = Content.fromAssetId(126749825185277)
local Editable = game:GetService("AssetService"):CreateEditableMeshAsync(obj, {FixedSize = true, SkinningEnabled = true})
local lightDirection =game.Lighting:GetSunDirection()
local objectCFrame = mesh.CFrame
ID = Editable:GetColors()
Face = Editable:GetFaces()
for i, FaceID in pairs(Face) do
local faceIndices = Editable:GetFaceNormals(FaceID)
local normal1 = (objectCFrame:VectorToWorldSpace(Editable:GetNormal(faceIndices[1])))
local normal2 = (objectCFrame:VectorToWorldSpace(Editable:GetNormal(faceIndices[2])))
local normal3 = (objectCFrame:VectorToWorldSpace(Editable:GetNormal(faceIndices[3])))
local faceNormal = (normal1 + normal2 + normal3).Unit
local dotProduct = faceNormal:Dot(lightDirection)
local colorids = Editable:GetFaceColors(FaceID)
if dotProduct > 0.7 then
for _, ids in pairs(colorids) do
Editable:SetColor(ids, Color3.new(1, 1, 1))
end
elseif dotProduct > 0.3 then
for _, ids in pairs(colorids) do
Editable:SetColor(ids, Color3.new(0.5, 0.5, 0.5))
end
else
for _, ids in pairs(colorids) do
Editable:SetColor(ids, Color3.new(0.3, 0.3, 0.3))
end
end
Editable:SetFaceColors(FaceID, colorids)
end
local finalMesh = game:GetService("AssetService"):CreateMeshPartAsync(Content.fromObject(Editable))
finalMesh.Parent = workspace
finalMesh.CFrame = objectCFrame
You can just edit the EditableMesh (var Editable) when you see fit. It should update the changes to the mesh I believe.
Is this intentional, or did I miss something in the post?
Could EditableImage::DrawImage* also take in a buffer
for its image parameter instead of solely an Object?
If I were to build a game engine and store the images (a lot of tiles) as a string/buffers/tables—which realistically have no size limitations—my biggest worry would be that EditableImages, which have a memory exhaust limit, might not always load.
Can assets that are able to load in a experience (like UGC or toolbox assets) be used for EditableImages and EditableMeshes in the future? These rules just don’t allow using an image from the toolbox and instead forces you to reupload it to your account / group while the asset can easily be downloaded with no problems from the website and it was distributed on the creator store with the creator’s approval (the option is disabled by default)
How would I make a flat plane? Previously before the deprecation of ‘EditableMesh:CreateMeshPartAsync’, I would pass a size through so that the Y size wasn’t 0 and the mesh wouldn’t be invisible. However, after these changes, I’m unsure how I would do this as my mesh is now completely invisible with a MeshSize Y of 0.
Also I’m not a 3d modeler and I won’t bother make 3d chaarcters, so I wait till they make their dummies publicly domain
Hello, I’m having a weird issue related to editable meshes where parenting a mesh part created with an editable mesh onto workspace starts to unrender objects in my game.
This is not a result of occlusion culling because I have the beta turned off.
(The object I’m changing the transparency of is a MeshPart with an EditableMesh applied onto it)
For some reason updating the editable mesh is a lot slower now as well. Unsure whether anyone else is experiencing this issue.
I get the permissions thing but can we still have access to some of the EditableMesh API even if we don’t own it? Like, GetFaces() or something? I have a plugin checking for mesh poly counts and its useless now because either the group owns the asset, or another user owns the asset. Something like read-only privileges would suffice I think.