EDIT : I have finished this program and it now has it’s own thread here.
Thank you everyone for the help!
Hi guys, I was planning on keeping this a secret, but I need some help.
I’m working on a program which will allow the user to basically take one item and turn it into many items of different colors.
When finished, it will generate the necessary QB, PNG, and JSON files as well as code for recipes and the manifest.
I’ve almost got it to the point where I am ready to let the community play with it, but I’ve run into a problem: It works perfectly generating colored QBs, except for orange. Just orange, everything else turns out great, but orange.
If you guys could have a look and give me your input that would be great
Below are snippets of my code which I think might be relevant to the problem. Also I’ve uploaded the vbproject onto github, If anyone want’s to take a look at all the (messy, somewhat uncommented) code >.>;
Somewhere in the code is the reason
This section defines the colors, the 3 numbers are Hue, Saturation, and Value.
Orange’s Hue is 30, but it comes out as 0, which is red, If I change it to 31 it comes out 60, which is yellow.
Public basicColors() As dye_color = { New dye_color("red", "Red", 0, 0, 0, False, False),
New dye_color("orange", "Orange", 30, 0, 0, False, False),
New dye_color("yellow", "Yellow", 60, 0, 0, False, False),
New dye_color("green", "Green", 125, 0, 0, False, False),
New dye_color("blue", "Blue", 210, 0, 0, False, False),
New dye_color("purple", "Purple", 275, 0, 0, False, False),
New dye_color("undyed", "Undyed", 40, 30, 0, True, False)}
This code converts QB’s format of Int32 colors into a more usable format of RGBA. (and back again)
Public Shared Function INT32toRGBA(ByVal int32 As Integer)
Dim bytes() As Byte = BitConverter.GetBytes(int32)
Return bytes
End Function
Public Shared Function RGBAtoINT32(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer, ByVal a As Integer)
Dim bytes() As Byte = New Byte() {r, g, b, a}
Dim int32 As Integer = BitConverter.ToInt32(bytes, 0)
Return int32
End Function
This code converts RGB(no A) into HSV so that I can easily change the Hue of the QB/PNG.
hsv(0) is Hue, hsv(1) is Saturation, and hsv(2) is Value
This code is based off the the code found here.
The extra 255 in saturation is to match it up to QB Constructs Color Dialog
Public Shared Function RGBtoHSV(ByVal r As Integer, ByVal g As Integer, ByVal b As Integer)
Dim hsv(2) As Integer
Dim min As Double, max As Double, delta As Double
If r <= g And r <= b Then min = r
If b <= g And b <= r Then min = b
If g <= r And g <= b Then min = g
If r >= g And r >= b Then max = r
If b >= g And b >= r Then max = b
If g >= r And g >= b Then max = g
hsv(2) = max
delta = max - min
If max <> 0 Then
hsv(1) = (delta / max) * 255
If r = max Then
hsv(0) = (g - b) / delta
ElseIf g = max Then
hsv(0) = 2 + (b - r) / delta
Else
hsv(0) = 4 + (r - g) / delta
End If
hsv(0) = hsv(0) * 60
If hsv(0) < 0 Then hsv(0) = hsv(0) + 360
If hsv(0) > 360 Then hsv(0) = hsv(0) - 360
Else
hsv(1) = 0
hsv(0) = 0
End If
Return hsv
End Function
This code converts it back to RGB
rgb(0) is red, rgb(1) is green, rgb(2) is blue.
This code is based off the the code found here.
The extra 255 in saturation is to match it up to QB Constructs Color Dialog
Public Shared Function HSVtoRGB(ByVal h As Integer, ByVal s As Integer, ByVal v As Integer)
Dim rgb(2) As Byte
Dim i As Long
Dim f As Double, p As Double, q As Double, t As Double
If s = 0 Then
rgb(0) = v
rgb(1) = v
rgb(2) = v
Else
h = h / 60
i = Math.Floor(h)
f = h - i
p = v * (1 - (s / 255))
q = v * (1 - (s / 255) * f)
t = v * (1 - (s / 255) * (1 - f))
Select Case i
Case 0
rgb(0) = v
rgb(1) = t
rgb(2) = p
Case 1
rgb(0) = q
rgb(1) = v
rgb(2) = p
Case 2
rgb(0) = p
rgb(1) = v
rgb(2) = t
Case 3
rgb(0) = p
rgb(1) = q
rgb(2) = v
Case 4
rgb(0) = t
rgb(1) = p
rgb(2) = v
Case 5
Case Else
rgb(0) = v
rgb(1) = p
rgb(2) = q
End Select
End If
Return rgb
End Function
And Finally, here is what reads every voxel of the QB file and recolors it if necessary.
QB is the original QB file
QB_NEG is a special file based on the original. All the pixels in QB which need recolored are black in QB_NEG.
Public Shared Function recolorQB(ByVal QB As QBModel, ByVal QB_NEG As QBModel, ByVal hue As Integer, ByVal sat As Integer, ByVal val As Integer, ByVal setSat As Boolean, ByVal setVal As Boolean)
Dim NewQB As New QBModel
NewQB = QB
'go through QB_NEG until a black voxel is found
For i As Integer = 1 To QB_NEG.getMatrixCount
Dim j As Integer = i - 1
For z As Integer = 0 To QB_NEG.matrix(j).data.GetLength(2) - 1
For y As Integer = 0 To QB_NEG.matrix(j).data.GetLength(1) - 1
For x As Integer = 0 To QB_NEG.matrix(j).data.GetLength(0) - 1
If QB_NEG.matrix(j).data(x, y, z) > 0 Then
Dim colorbytes() As Byte = INT32toRGBA(QB_NEG.matrix(j).data(x, y, z))
If colorbytes(0) = 0 And colorbytes(1) = 0 And colorbytes(2) = 0 And colorbytes(3) <> 0 Then 'voxel is visible and pure black
'open that voxel in NewQB
'convert int32color to rgba, rgba to hsv
Dim rgba() As Byte = INT32toRGBA(NewQB.matrix(j).data(x, y, z))
Dim hsv() As Integer = RGBtoHSV(rgba(0), rgba(1), rgba(2))
'change hue
hsv(0) = hue
'change saturation
If setSat Then
hsv(1) = sat
Else
hsv(1) = hsv(1) + sat
End If
'change value
If setVal Then
hsv(2) = val
Else
hsv(2) = hsv(2) + val
End If
'make sure hsv is in the correct bounds
If hsv(0) < 0 Then hsv(0) = 0
If hsv(0) > 360 Then hsv(0) = 360
If hsv(1) < 0 Then hsv(1) = 0
If hsv(1) > 255 Then hsv(1) = 255
If hsv(2) < 0 Then hsv(2) = 0
If hsv(2) > 255 Then hsv(2) = 255
'convert new hsv to rgba (using original a)
Dim rgba_temp() As Byte = HSVtoRGB(hsv(0), hsv(1), hsv(2))
rgba(0) = rgba_temp(0)
rgba(1) = rgba_temp(1)
rgba(2) = rgba_temp(2)
'convert rbga to int32color
'set voxel in NewQB to int32color
NewQB.matrix(j).data(x, y, z) = RGBAtoINT32(rgba(0), rgba(1), rgba(2), rgba(3))
End If
End If
Next
Next
Next
Next
Return NewQB
End Function
Any help anyone can give would be greatly appreciated!
I’m going to go digging through the code again and hope something pops up.