- What do you want to achieve?
I want to make it so the editable image displays a height map from black to white based on a randomly generated number.
-
What is the issue? Include screenshots / videos if possible!
The issue is that the image is only showing a single color at once, almost like it’s ignoring the math.random()
-
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’ve tried switching from draw rectangles to write pixels, and back, and I’ve searched on the developer hub for solutions, but I couldn’t find any posts on the topic.
EditableImage:Resize(Vector2.new(1024, 1024))
local image_size = EditableImage.Size
-- Create an array to store pixel data
local pixel_data = {}
-- Loop through each pixel in the image
for y = 0, image_size.Y - 1 do
for x = 0, image_size.X - 1 do
-- Generate a floating-point random number between 0 and 1 for depth
local num = math.random(0.0000, 1.0000)
-- Use grayscale value for the depth
local vertex_color = Color3.new(num, num, num)
-- Add the color data (R, G, B, A) to the pixel array, converted to [0, 255] range
table.insert(pixel_data, math.floor(vertex_color.R * 255)) -- Red
table.insert(pixel_data, math.floor(vertex_color.G * 255)) -- Green
table.insert(pixel_data, math.floor(vertex_color.B * 255)) -- Blue
table.insert(pixel_data, 255) -- Alpha (fully opaque)
end
end
EditableImage:WritePixels(Vector2.new(0, 0), image_size, pixel_data)
If the full context for generating the plain mesh itself is needed, I’ll send the full script.
A few things are incorrect with your script.
math.random()
will only return a whole number, a solution is to use Random and :NextNumber()
without any arguments.
local random = Random.new()
local num = random:NextNumber() -- will return between 0 and 1, including decimals
Next, you are inserting pixels that are equivalent to the actual RGB values. :WritePixels()
accepts R,G,B,A as you are aware, though those values are meant to be between 0 and 1. To fix this, you can just remove the math.floor()
and * 255
you have. If you want to keep a certain amount of decimals, you can just do something like this:
local num = random:NextNumber() -- 0.295129102
num = math.floor(num * 10000)/10000 -- 0.2951
After this, you can just insert these values into the pixel_data
table and it should be all grayscale values.
1 Like
The reply above my own should be the solution to your problem.
I’m replying as I wish to add that math.random()
(without any parameters given) returns a decimal number between 0 and 1, meaning that you can just remove the 0.0000 and 1.0000 to get the desired randomness, rather than having to use Random:NextNumber()
I think it may have something to do with the way the plain was scripted, because even after making all of these changes, the entire plain is only ever turning one color.
This is my code I wrote to create the plain:
parts[part] = {}
parts[part].editablemesh = EditableMesh
local Vertices = {}
for y = 1, HEIGHT do
local raw = {}
for x = 1, WIDTH do
local vertex_position = (Vector3.new(x-1, 0, y-1) - Vector3.new(WIDTH / 2, 0, HEIGHT / 2)) * Offset
local vertex_id = EditableMesh:AddVertex(vertex_position)
-- Precompute a random phase offset and store it along with the vertex
local phaseOffset = Vector3.new(math.random() * PhaseScale, 0, math.random() * PhaseScale)
-- Precompute a random speed variation and store it along with the vertex
local speedVariation = 1 + (math.random() - 0.5) * 0.1
raw[x] = {vertex_id, vertex_position, phaseOffset, speedVariation}
end
Vertices[y] = raw
end
for y = 1, HEIGHT-1 do
for x = 1, WIDTH-1 do
local vertex_1 = Vertices[y][x][1] :: number
local vertex_2 = Vertices[y+1][x][1] :: number
local vertex_3 = Vertices[y][x+1][1] :: number
local vertex_4 = Vertices[y+1][x+1][1] :: number
local triangle_1 = EditableMesh:AddTriangle(vertex_1, vertex_2, vertex_3)
local triangle_2 = EditableMesh:AddTriangle(vertex_2, vertex_4, vertex_3)
end
end
parts[part].verticies = Vertices
I can’t seem to figure out why.
It’s how Roblox tries to project an EditableImage on to a Mesh with an EditableMesh thats the issue. I believe that’s why they are creating the method :DrawProjectionImage(), which is currently disabled.
There are still a few potential solutions. If you have a flat plane, and will NOT be modifying the actual height of the EditableMesh, you can just use a SurfaceGUI with it’s adornee property set to the Mesh. The EditableImage should be parented to an ImageLabel inside of SurfaceGUI.
If you are modifying the height of the EditableMesh, rather than using an EditableImage, you can use vertex coloring on the EditableMesh using :SetFaceColors(). SetFaceColors takes in a FaceId which you can get from :GetFaces() and a table of Colors created using :AddColor().
Example:
-- This sets each quad(2 tris) to a whole color, as if it were an EditableImage
local faces = EditableMesh:GetFaces()
for index, faceId in pairs(faces) do
if index % 2 == 0 then
local previousFaceColors = EditableMesh:GetFaceColors(faces[index-1])
EditableMesh:SetFaceColors(faceId, previousFaceColors)
else
local randomColor = math.random()
local newColor = EditableMesh:AddColor(Color3.new(randomColor, randomColor, randomColor), 1)
EditableMesh:SetFaceColors(faceId, {newColor, newColor, newColor})
end
end
The only other solution is to use :SetUV() if you are really adamant on using an EditableImage. I haven’t messed with it enough to be able to provide with the information on how to use it in your situation, but I know it will let you use EditableImage on your EditableMesh. THIS POST has an example place you can download and search for :SetUV()
in, but keep in mind you’ll have to make your own way of setting UVs as this is based on its own EditableMeshes and situation.
There probably is a different/better solution than what I provided, but hopefully this can help provide some solution to your question.