So if I have a color, how can I get the closest material to that color? I want this for terrain, and I think I can use GetMaterialColor to do this but I’m not sure.
Elaborate? there is no way to change a material to a color or a color to a material.
Unless you directly matchthese “material colors”
To get the closest you would have to use something like the levenshtein distance. It is, complicated but might work for your situation.
Still Dont Understand?
We’ll use this function to see the levenshtein distance. These scripts were made from ChatGPT…
function Levenshtein(str1, strArray)
local distances = {}
-- Iterate over the array of strings
for index, str2 in ipairs(strArray) do
local len1 = #str1
local len2 = #str2
-- Create a table to hold the distances
local distance = {}
-- Initialize the first row and column of the distance table
for i = 0, len1 do
distance[i] = {}
distance[i][0] = i
end
for j = 0, len2 do
distance[0][j] = j
end
-- Compute the distances
for i = 1, len1 do
for j = 1, len2 do
local cost = (str1:sub(i, i) == str2:sub(j, j)) and 0 or 1
distance[i][j] = math.min(
distance[i-1][j] + 1, -- Deletion
distance[i][j-1] + 1, -- Insertion
distance[i-1][j-1] + cost -- Substitution
)
end
end
-- Store the final distance for this string in the array
distances[index] = distance[len1][len2]
end
return distances
end
Testing it out.
local baseString = "kitten"
local comparisonStrings = {"sitting", "bitten", "kitchen"}
local distances = Levenshtein(baseString, comparisonStrings)
for i, dist in ipairs(distances) do
print("Levenshtein Distance to", comparisonStrings[i], ":", dist)
end
-- Output:
-- Levenshtein Distance to sitting : 3
-- Levenshtein Distance to bitten : 1
-- Levenshtein Distance to kitchen : 3
As we can see, bitten is close to kitten, so we will say its similar. using this same function we can make this;
New Function
function LevenshteinClosestMatch(str1, strArray)
local closestMatch = nil
local minDistance = math.huge -- Initialize with a very large number
local distances = {}
-- Iterate over the array of strings
for index, str2 in ipairs(strArray) do
local len1 = #str1
local len2 = #str2
-- Create a table to hold the distances
local distance = {}
-- Initialize the first row and column of the distance table
for i = 0, len1 do
distance[i] = {}
distance[i][0] = i
end
for j = 0, len2 do
distance[0][j] = j
end
-- Compute the distances
for i = 1, len1 do
for j = 1, len2 do
local cost = (str1:sub(i, i) == str2:sub(j, j)) and 0 or 1
distance[i][j] = math.min(
distance[i-1][j] + 1, -- Deletion
distance[i][j-1] + 1, -- Insertion
distance[i-1][j-1] + cost -- Substitution
)
end
end
-- Store the final distance for this string
local currentDistance = distance[len1][len2]
distances[index] = currentDistance
-- Check if this is the smallest distance found so far
if currentDistance < minDistance then
minDistance = currentDistance
closestMatch = str2
end
end
return closestMatch, minDistance, distances
end
New Iteration
local baseString = "kitten"
local comparisonStrings = {"sitting", "bitten", "kitchen", "mitten"}
local closestMatch, minDistance, distances = LevenshteinClosestMatch(baseString, comparisonStrings)
print("Closest Match:", closestMatch)
print("Levenshtein Distance:", minDistance)
-- Output:
-- Closest Match: bitten
-- Levenshtein Distance: 1
--modify this as you like
--this uses Euclidean distance instead of levenshtein
local function getColorDistance(c1: Color3, c2: Color3): number
local v1 = Vector3.new(c1.R, c1.G, c1.B)
local v2 = Vector3.new(c2.R, c2.G, c2.B)
return (v2-v1).Magnitude
end
--gets all materials that wont error the GetMaterialColor function
local function getTerrainMaterials(): {[Enum.Material]: Color3}
local materials = {}
for _, material in pairs(Enum.Material:GetEnumItems()) do
pcall(function()
materials[material] = workspace.Terrain:GetMaterialColor(material)
end)
end
return materials
end
local function getClosestMaterial(color: Color3): Enum.Material
local current, distance = nil, nil
for material, c in pairs(getTerrainMaterials()) do
local d = getColorDistance(color, c)
if not current or d < distance then
current, distance = material, d
end
end
return current
end
--Green/Lime -> Enum.Material.LeafyGrass
print(getClosestMaterial(Color3.new(0, 1, 0)))
Can you make this work with water? Also can you explain the syntax here? I barely understand it lol.
To make it work with water:
--gets all materials that wont error the GetMaterialColor function
local function getTerrainMaterials(): {[Enum.Material]: Color3}
local materials = {}
for _, material in pairs(Enum.Material:GetEnumItems()) do
pcall(function()
materials[material] = workspace.Terrain:GetMaterialColor(material)
end)
end
materials[Enum.Material.Water] = workspace.Terrain.WaterColor
return materials
end
The syntax means that the function returns a dictionary/mapping with materials as keys and colors as values.
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.