[Studio Beta] Major updates to in-experience Mesh & Image APIs

I’m getting the image from ImageLabel.ImageContent
Even fromUri still return the same

I can see myself making great use of this API in the future. Good work.

1 Like

Also please update the Documentations for EditableMesh and EditableImage, they are outdated

What’s up with the mesh size limits? They’ve completely broken any kind of LOD generation.

I strongly second this, having parallel lua bulk methods would be a dream. I’m trying to fast load procedural maps with terrain, plants, cities, the whole shabang for a strategy game. I’ve cut it down to less than 45 seconds for a 4000x4000 map with high detail but this update it shot it up to 200 seconds. Might have to figure out if I did something wrong, but parallel lua methods would always help by making it so I don’t have to keep synchronizing when making the maps :slight_smile:

Take a look at the code snippets provided in the post. Once you set up your EditableMesh, you can use Live Rendering an EditableMesh to achieve what you need. Once you create the linked MeshPart any changes to the underlying EditableMesh object live render just like the previous approach of parenting it underneath the MeshPart

As the post mentioned, all properties that point to content with IDs will eventually be converted to Content wrappers. They will all be backwards compatible. See the last portion of the Content section of the post

That’s fair feedback and the use case you are building makes sense. We’ll take that into account for future iterations of the permissions rules. Maybe something like checking permissions only on publishing rather than when loading might help in this scenario and some of the others mentioned in this topic.

What features are you missing to accomplish this today?

Yes! We are working on it… should hopefully have these updated very soon (in the next few days)

2 Likes

You can just use this line which is the equivalent of EditableImage:Clear(). This just “draws a transparent rectangle” starting at 0,0 up to the size of the image

myEditableImage:DrawRectangle(Vector2.zero, myEditableImage.Size, Color3.new(0, 0, 0), 1, Enum.ImageCombineType.Overwrite)

This is likely due to the fact that editableMesh:CreateMeshPartAsync() requires a MeshSize parameter that you are setting to (1,1,1) and that is doing a scale under the hood which is then hitting the mesh size bounds.

I just updated the original post to include a code snippet to calculate the extents of your editableMesh which can then be passed in as the parameter for MeshSize.

Here it is again to save you the trouble of looking through the post again:

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

and then instead of using: Vector3.one you would just do:

editableMesh:CreateMeshPartAsync(computeExtents(editableMesh))
2 Likes

The current features support this, my question was more is there an ETA for when the more basic features will be available to be used ingame rather than as a studio beta.
I have no need for replication (and the interesting problems that I’m sure deciding how to implement it) for my use case.

I’m having a problem with my meshes getting culled. My terrain is composed of meshParts with Size 1,1,1; while their editableMeshes vertices can be even 64 studs away from the meshPart. Should i keep all vertices inside meshParts? Before this update, these meshes weren’t being culled.

7 Likes

Did a bit more testing and I realized that the reason behind EditableMeshes not appearing wasn’t because of the new Content system, but rather due to AssetService being the only way to run CreateEditableMeshAsync in rapid succession and the API couldn’t keep up :sad:

Not sure if there’s any fix for this, but I hope that there will be some way to overcome this other than just being forced to wait longer in-between asset creation.

The video below is just a test on how it’d work for those different assets that I don’t have at the moment, as my use-case for this was going to be effects for character creation and some environmental assets without having to wait extended periods of time, but I might be out of luck.

1 Like

This complete revamp of the whole system and the support for so many new Instances like ViewportFrames is definitly useful and I have some use cases in mind, didn’t expect them to become Objects though, but it definitly opens new possibilities.

For now it’s still experimental, but I think just like the CSG-API, it will be slowly usable in games.

Can you expand a bit more on how you are calling CreateEditableMeshAsync? Are you calling this every frame for some reason?

Could you drop in the code you are using to call CreateEditableMeshAsync in rapid succession so we can understand more of the context here?

If you’re calling AssetService:CreatEditableMeshAsync(...) every frame to effectively Clone() the original mesh that’s going to be pretty sub-optimal… That async from-asset method does unconditionally yield a frame currently too, even if the mesh is already loaded.

If you’re just trying to update the vertex positions every frame consider copying the original positions into an array and just clone that, e.g…

local function getVertexPositions(em: EditableMesh): ({ number }, { Vector3 })
	local vIds = em:GetVertices()
	local vPositions = table.create(#vIds)
	for i, vid in vIds do
		vPositions[i] = em:GetPosition(vid)
	end
	return vIds, vPositions
end

local function setVertexPositions(em: EditableMesh, vIds: { number }, vPositions: { Vector3 })
	for i, vid in vIds do
		em:SetPosition(vid, vPositions[i])
	end
end

-- Keep the original positions around...
local vertexIds, vertexPositions = getVertexPositions(em)

-- ...

local function updatePositions()
	local newPositions = table.create(#vertexPositions)
	for i, pos in vertexPositions do
		newPositions[i] = vertexPositions[i] * 2 -- Insert vertex transformation here...
	end
	setVertexPositions(em, vertexIds, newPositions)
end

(Sorry, I know we need a batch API already…)

I’d still caution against doing this for transformations like what you’re showing in your video or any kind of “realtime” vertex shader style effects…

EditableMeshes still use a lot of memory, are much more expensive to update for rendering since we have to transcode and re-upload the whole mesh to the GPU every frame if they’re updated.

Especially when you’re updating them every frame it also defeats a lot of the engine’s scalability systems, and makes it impossible for us to do any kind of LOD on that mesh.

If it’s something you can do with just CFrame updates or skinned meshes those are much better choices for effects! We just need to reupload a few bone transforms, and then skinning happens on the GPU.

I know a lot of people will do this anyway, but please be very cautious about how you use it and use it sparingly!

3 Likes

How I’ve been creating the editable meshes is just using the tag system, iterating through what meshes have this tag, and then going through a for-loop to just create the editable mesh once per object. This function is separate from the one that actually updates the editable meshes at all.

I do not create a new editable mesh every frame, as my pc would probably explode alongside just throwing out those same errors :uhh:

I save the editable mesh to a table so I can reference back to it and that’s how it’s worked for me. I’ve tried just putting a task.wait(1) at the end of the loop

The one that’s been able to keep up is task.wait(5), which is pretty long considering that a character or object could have 3-8 different meshes, and It’d be pretty annoying for the user experience to have to wait that long only to have the meshes converted.

Yep! I do think that something like this should be completely handled on the GPU, but at the moment Roblox doesn’t support those kinds of operations, so I’m stuck with the cards I got.

I would like to say that I already do save the data of editable meshes in tables so I can reference back to them, and that I’ve had to make a system that progressively doesn’t call for an update as often if there’s too many nearby or if it’s farther away! (As far as I’m aware it’s mostly the updating of the editable mesh that causes issues and not just creating an editable mesh?)

I do know that this is going to be pretty taxing even with the mega optimizations that you guys do alongside some of my own, which is why I’m going to try to be sparing with how many can be around at a time! People can’t enjoy the work involved if their device is on fire after all.

If it’d help I can send the file to your DMs so you can take a look at it.

There’s a mistake in this example, Color3.new(0, 255, 0) should be Color3.fromRGB(0, 255, 0).

The Experience in the post named “Hubcap_Image_v21.rbxl” (for download) , there are some errors in the scripts and can’t test it!

1 Like

their same vague “you can’t use IDs that don’t belong to you” system. Disappointing. I mean, I had a mesh rendering system, how do I render a texture that is not mine?

image

This update broke my game :melting_face: I’m getting too many requests despite the fact that it worked just fine before the update went live. I think what happened is:

Before the update:

  1. Calls AssetService:CreateEditableMeshFromPartAsync
  2. Engine creates and returns EditableMesh

After the update:

  1. Calls AssetService:CreateEditableMeshFromPartAsync
  2. Engine makes an HTTP request to Roblox API to check the owner of the asset
  3. If ownership check passes, engine creates and returns EditableMesh, otherwise throws an error

So now my script takes 3s+ to execute alongside all the “Too Many Requests” errors. Before the update it only took about a millisecond, if not less.

2 Likes