Converting color3 to hsv, but also positioning on a color wheel

I have a color wheel, that gives me an hsv color value. I then use this to get a Color3 object.

However, when I start with a color3, I am lost as to how to convert it to hsv.
And even if I did find how to convert color3 to hsv, how would I map the h, s, onto a color wheel, as the v is just the darkness slider?

Any help is appreciated, thanks

function WheelMath(input)
	local r = Wheel.AbsoluteSize.x/2
	local d = Vector2.new(input.Position.x, input.Position.y) - Wheel.AbsolutePosition - Wheel.AbsoluteSize/2

	if (d:Dot(d) > r*r) then
		d = d.unit * r
	end	
	WheelMarker.Position = UDim2.new(.5, d.x, .5, d.y)
	
	GetColor()
end
local function GetColor()
	local wheelCenter = Vector2.new(
		Wheel.AbsolutePosition.X + (Wheel.AbsoluteSize.X/2), 
		Wheel.AbsolutePosition.Y + (Wheel.AbsoluteSize.Y/2))
	local markerCentre = Vector2.new(
		WheelMarker.AbsolutePosition.X + (WheelMarker.AbsoluteSize.X/2),
		WheelMarker.AbsolutePosition.Y + (WheelMarker.AbsoluteSize.Y/2))
	local h = (math.pi - math.atan2(markerCentre.Y - wheelCenter.Y, markerCentre.X - wheelCenter.X)) / (math.pi * 2)
	local s = (wheelCenter - markerCentre).Magnitude / (Wheel.AbsoluteSize.X/2)

	Slider.UIGradient.Color = ColorSequence.new{
		ColorSequenceKeypoint.new(0, Color3.fromHSV(math.clamp(h, 0, 1), math.clamp(s, 0, 1), 1)), 
		ColorSequenceKeypoint.new(1, Color3.new(0, 0, 0))
	}
	local color = Color3.fromHSV(math.clamp(h, 0, 1), math.clamp(s, 0, 1), math.clamp(Value, 0, 1))
	Swatch.BackgroundColor3 = color
	Result.Value = color	
	
end

What does the color wheel look like?

image

First of all, there is a constructor specifically for turning RGB into HSV

And to position it on the color wheel, you can treat it like a unit circle


Where angle is the hue and radius is the saturation. Value is on a separate slider so it doesn’t matter

local hue, sat, val = color:ToHSV()
local angle = hue * math.pi * 2 --since hue is 0 to 1, we convert it to radians by multiplying 2pi

Then, we can get the Vector2 offset based on the unit circle:

local vec = Vector2.new(math.cos(angle), math.sin(angle))

This vector describes the direction of the offset of the pointer from the center of the color wheel.

To get the length of the vector, we take the saturation value and interpolate it along the radius of the wheel:

local radius = wheel.AbsoluteSize * .5
local pointerPos = vec * radius * sat

And finally, we get the origin of the wheel and add that to the vector to get the position of the pointer:

local originPos = wheel.AbsolutePosition + radius --radius is still a vector!!
pointer.Position = UDim2.new(0, pointerPos.X + originPos.X, 0, pointerPos.Y + originPos.Y)

Note that if the pointer appears to be offset by a constant angle around the wheel, you can simply just add that constant back to the angle to correct it, for example

angle = (hue * math.pi * 2) + math.pi --offset by 180 degrees
6 Likes

Thank you so much, its working now.