314 lines
8.5 KiB
Plaintext
Executable File
314 lines
8.5 KiB
Plaintext
Executable File
struct PaletteOps
|
|
(
|
|
--palette index is the palette table entry
|
|
--it contains an array of a colour and object verts indexes
|
|
-- palette[1] = #(#((color 255 255 255), 3, 5, 44, 155), #((color 255 12 34), 12, 55, 8, 205), .....)
|
|
palette = dotNetObject "RSG.MaxUtils.MaxDictionary", --key=colour value=#(mapverts)
|
|
--translator = dotNetObject "RSG.MaxUtils.MaxDictionary", --key=colour value = paletteindex
|
|
--indexToColour = dotNetObject "RSG.MaxUtils.MaxDictionary", --key = index value=colour
|
|
indexToColour = #(),
|
|
paletteIdx = #(),
|
|
|
|
--Grab the vertex colours from the selected mesh and channel
|
|
fn grabMeshColours channel:13 obj:$selection[1] =
|
|
(
|
|
--obj = $selection[1]
|
|
--clear the dict
|
|
palette.clear()
|
|
|
|
if (meshop.getMapSupport obj.mesh channel) != true then return false
|
|
|
|
theMesh = snapShotAsMesh obj
|
|
for mv = 1 to (meshOp.getNumMapVerts theMesh channel) do
|
|
(
|
|
mapVertColour = meshOp.getMapVert theMesh channel mv
|
|
--colourVec = dotNetObject "RSG.Base.Math.Vector3f" mapVertColour.x mapVertColour.y mapVertColour.z
|
|
colourVec = dotNetObject "System.Windows.Media.Media3D.Point3D" mapVertColour.x mapVertColour.y mapVertColour.z
|
|
--print mapVertColour
|
|
--try and add it to the dictionary, if its already there then append the mv index to the value array
|
|
if palette.containsKey colourVec == true then
|
|
(
|
|
val = append palette.item[colourVec] mv
|
|
palette.remove colourVec
|
|
palette.add colourVec val
|
|
)
|
|
else
|
|
(
|
|
palette.add colourVec #(mv)
|
|
|
|
--add colourToPaletteIndex
|
|
append indexToColour colourVec
|
|
)
|
|
)
|
|
|
|
format "Colours Grabbed: % \n" palette.count
|
|
),
|
|
|
|
|
|
--reduce the number of entries in the item to maxColours
|
|
--merge the two closest pairs of colours until we hit maxColours
|
|
fn reduce maxColours =
|
|
(
|
|
if maxColours > palette.count then return false
|
|
|
|
point3D = dotNetClass "System.Windows.Media.Media3D.Point3D"
|
|
|
|
progressStart "Reducing: "
|
|
progressRange = palette.count - maxcolours
|
|
|
|
while palette.count > maxColours do
|
|
(
|
|
colourDistance = #()
|
|
paletteIt = palette.keys.getEnumerator()
|
|
innerIt = palette.keys.getEnumerator()
|
|
|
|
--start = timestamp()
|
|
while paletteIt.moveNext() != false do
|
|
(
|
|
colourA = paletteIt.current
|
|
--loop over the dict entries.
|
|
while innerIt.moveNext() != false do
|
|
(
|
|
colourB = innerIt.current
|
|
|
|
--get the distance between the two colours
|
|
vec = point3D.subtract colourA colourB
|
|
|
|
if vec.length > 0.0 then
|
|
(
|
|
--closest = DataPair distance:dist colours:#(colourA, colourB)
|
|
append colourDistance (DataPair distance:vec.length colours:#(colourA, colourB))
|
|
)
|
|
)
|
|
)
|
|
--end = timestamp()
|
|
--format "distance calc: % \n" ((end - start) / 1000.0)
|
|
|
|
--sort or pick the lowest distance pair
|
|
theDistances = for i in colourDistance collect i.distance
|
|
sort theDistances
|
|
closest = (for d in colourDistance where d.distance == theDistances[1] collect d)[1]
|
|
|
|
colourA = closest.colours[1]
|
|
colourB = closest.colours[2]
|
|
|
|
--combine the mapvert index arrays
|
|
combineIndices = #()
|
|
join combineIndices palette.item[colourA]
|
|
join combineIndices palette.item[colourB]
|
|
|
|
--combine palette indexes
|
|
colourA_idx = findItem indexToColour colourA
|
|
colourB_idx = findItem indexToColour colourB
|
|
|
|
indexToColour[colourA_idx] = undefined
|
|
indexToColour[colourB_idx] = undefined
|
|
|
|
--take the average of the 2 colours
|
|
r = colourA.x + (0.5 * (colourB.x - colourA.x))
|
|
g = colourA.y + (0.5 * (colourB.y - colourA.y))
|
|
b = colourA.z + (0.5 * (colourB.z - colourA.z))
|
|
newColour = dotNetObject "System.Windows.Media.Media3D.Point3D" r g b
|
|
|
|
--remove the 2 old colours
|
|
palette.remove colourA
|
|
palette.remove colourB
|
|
|
|
--add the new averaged colour with the combined mapvert index array
|
|
palette.add newColour combineIndices
|
|
append indexToColour newColour
|
|
|
|
--
|
|
--end = timestamp()
|
|
--format "reduce calc: % \n" ((end - start) / 1000.0)
|
|
--print "."
|
|
|
|
progressUpdate (100.0 * (palette.count - maxColours) / progressRange)
|
|
)
|
|
|
|
--remove dead indices from indexToColour
|
|
indexToColour = for col in indexToColour where col != undefined collect col
|
|
|
|
progressEnd()
|
|
),
|
|
|
|
|
|
fn paintToMesh channel =
|
|
(
|
|
--flush
|
|
for v = 1 to (meshop.getnummapverts $ channel) do meshop.setmapvert $ channel v [0, 0, 0]
|
|
update $
|
|
--iterate the palette keys setting the values(mapverts) to the key colour
|
|
palIt = palette.keys.getEnumerator()
|
|
|
|
while palIt.moveNext() != false do
|
|
(
|
|
theColour = palIt.current
|
|
mapVerts = palette.item[theColour]
|
|
|
|
theColour = [theColour.x, theColour.y, theColour.z]
|
|
for v in mapVerts do
|
|
(
|
|
meshop.setmapvert $ channel v theColour
|
|
)
|
|
)
|
|
|
|
update $
|
|
CompleteRedraw()
|
|
),
|
|
|
|
fn genPaletteIndexes =
|
|
(
|
|
for i = 1 to indexToColour.count do
|
|
(
|
|
for mv = 1 to palette.item[indexToColour[i]].count do
|
|
(
|
|
paletteIdx[palette.item[indexToColour[i]][mv]] = i
|
|
)
|
|
)
|
|
--format "paletteIdx count: % \n" paletteIdx.count
|
|
),
|
|
|
|
--insert an entry into the item at position idx
|
|
fn insert idx =
|
|
(
|
|
|
|
),
|
|
|
|
--remove and entry from the item and position idx
|
|
fn remove idx =
|
|
(
|
|
|
|
),
|
|
|
|
--remove any empty indexes by adjusting item indexes into empty slots
|
|
fn compact =
|
|
(
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
struct ClonePal
|
|
(
|
|
clonePals = #(),
|
|
paletteCount = 4,
|
|
masterPal = #(),
|
|
|
|
fn combinePalettes clones:$selection =
|
|
(
|
|
--reduce each object palette to an equal number of entries
|
|
--clones = $selection
|
|
|
|
for obj in clones do
|
|
(
|
|
--create a pop instance
|
|
pOp = PaletteOps()
|
|
pOp.grabMeshColours channel:13 obj:obj
|
|
pOp.reduce paletteCount
|
|
pOp.genPaletteIndexes()
|
|
append clonePals pOp
|
|
)
|
|
|
|
),
|
|
|
|
/*
|
|
fn gather =
|
|
(
|
|
--so row 1 is the master, we trawl the other palettes looking for the closest match, then we update the indices to match the position of row1
|
|
theOriginal = clonePals[1]
|
|
for p = 2 to clonePals.count do
|
|
(
|
|
--for each palette entry
|
|
for c = 1 to clonePals[p]
|
|
|
|
)
|
|
|
|
),
|
|
*/
|
|
|
|
|
|
fn reorder =
|
|
(
|
|
--reorder palette entries so each mapvert id is only in one column
|
|
|
|
--create a new array to hold the new palette
|
|
--masterPal = #()
|
|
|
|
--start with the first palette to compare against the others, this will be row 0
|
|
/*
|
|
rowZeroConstruct = dotNetObject "System.Object[]" paletteCount
|
|
clonePals[1].palette.values.copyTo rowZeroConstruct 0
|
|
rowZero = for i = 0 to (rowZeroConstruct.length - 1) collect rowZeroConstruct.getValue[i] as BitArray
|
|
*/
|
|
--rowZeroRaw = clonePals[1].palette.item[clonePals[1].indexToColour[1]]
|
|
--rowZero = rowZeroRaw as BitArray
|
|
|
|
--print rowZero
|
|
--add this first clonepal to the master
|
|
theOriginal = clonePals[1]
|
|
append masterPal theOriginal
|
|
|
|
--now sort out the rest
|
|
for pal = 2 to clonePals.count do
|
|
(
|
|
--the clone this iteration
|
|
theClone = clonePals[pal]
|
|
|
|
--the mapvert indices
|
|
palRowRaw = theClone.palette.item[theClone.indexToColour[1]]
|
|
|
|
for i = 1 to theOriginal.indexTocolour.count do
|
|
(
|
|
--format "i = % \n" i
|
|
orig_mv_Idxs = theOriginal.palette.item[theOriginal.indexToColour[i]] as BitArray
|
|
--format "orig_mv_Idxs: % \n" orig_mv_Idxs
|
|
|
|
for j = 1 to theClone.indexToColour.count do
|
|
(
|
|
--format "j = % \n" j
|
|
clone_mv_Idxs = theClone.palette.item[theClone.indexToColour[j]] as BitArray
|
|
--format "clone_mv_Idxs: % \n" clone_mv_Idxs
|
|
|
|
--if they cancel out then they match
|
|
--format "orig - clone: % \n" (orig_mv_Idxs - clone_mv_Idxs)
|
|
if orig_mv_Idxs * clone_mv_Idxs != #{} then
|
|
(
|
|
--swap j for i in the clone indexToColours
|
|
theSwap = theClone.indextoColour[i]
|
|
theClone.indextoColour[i] = theClone.indextoColour[j]
|
|
theClone.indextoColour[j] = theSwap
|
|
)
|
|
)
|
|
)
|
|
|
|
--generate the palette indices
|
|
theClone.genPaletteIndexes()
|
|
|
|
append masterPal theClone
|
|
/*
|
|
palIdx = 0
|
|
indexArray = dotNetObject "System.Object[]" paletteCount
|
|
palNextRaw = clonePals[pal].palette.values.copyTo indexArray 0
|
|
|
|
--convert palette indices as bitarray and compare using that
|
|
palNext = clonePals[pal].palette.item[clonePals[1].indexToColour[1]] as BitArray
|
|
|
|
--compare
|
|
for i = 1 to rowZero.count do
|
|
(
|
|
for j = 1 to palNext.count do
|
|
(
|
|
if rowZero[i] == palNext[j] then palIdx = i
|
|
)
|
|
)
|
|
*/
|
|
)
|
|
|
|
--print masterPal
|
|
|
|
)
|
|
)
|
|
|