Проблема, с которой я столкнулся, заключается в том, что я хочу раскрасить сложные модели (+ 4k треугольников), не разбивая модели на множество объектов TriangleMesh.
Насколько я понимаю, это можно сделать только путем сопоставления цветов на изображении, а затем вычисления текстурных координат каждого цветового пикселя на изображении.Что я сделал ниже:
val uniqueColors = colors.toHashSet()
val colorTexCoordsMap = HashMap<Color, FloatArray>()
val atlas = WritableImage(uniqueColors.size, 1)
for((index, color) in uniqueColors.withIndex()) {
colorTexCoordsMap[color] = floatArrayOf(index.toDouble().div(uniqueColors.size).toFloat(), 0.5f)
atlas.pixelWriter.setColor(index, 0, color)
}
atlasMaterialProperty.set(PhongMaterial().also {
it.diffuseMap = atlas
})
val out = File("model-${definition.id}-${uniqueColors.size}-atlas.png")
val bim = SwingFXUtils.fromFXImage(atlas, null)
ImageIO.write(bim, "png", out)
for(face in 0 until definition.faceCount){
val color = colors[face]
val uv = colorTexCoordsMap[color]!!
val vertex1 = definition.faceVertexIndices1[face]
val vertex2 = definition.faceVertexIndices2[face]
val vertex3 = definition.faceVertexIndices3[face]
val vx1 = definition.vertexPositionsX[vertex1]
val vy1 = definition.vertexPositionsY[vertex1]
val vz1 = definition.vertexPositionsZ[vertex1]
val vx2 = definition.vertexPositionsX[vertex2]
val vy2 = definition.vertexPositionsY[vertex2]
val vz2 = definition.vertexPositionsZ[vertex2]
val vx3 = definition.vertexPositionsX[vertex3]
val vy3 = definition.vertexPositionsY[vertex3]
val vz3 = definition.vertexPositionsZ[vertex3]
val vertex1Index = cacheVertex(vertex1, vx1, vy1, vz1)
val vertex2Index = cacheVertex(vertex2, vx2, vy2, vz2)
val vertex3Index = cacheVertex(vertex3, vx3, vy3, vz3)
val texIndex = cacheUV(uv[0], uv[1])
faces.addAll(
vertex1Index, texIndex,
vertex2Index, texIndex,
vertex3Index, texIndex
)
faceSmoothingGroups.addAll(0)
}
Я ожидал, что цвета будут отображаться точно, но это не так.Я думаю, что это связано с тем, что часть деления не очень точная, и поэтому в моделях, которые используют много цветов, иногда уф-координата больше не отображается на предполагаемый цвет в сгенерированном изображении.
В текущем коде генерируется изображение с высотой = 1 и шириной = цвет_счетом.Таким образом, каждое значение x представляет индекс цвета.Я также попытался сгенерировать больше прямоугольных палитр, чтобы уменьшить количество делений, это помогло в некоторых случаях, но не в других, в зависимости от того, сколько цветов присутствует в модели.
Редактировать: заставил работать со следующимикод:
for((index, color) in uniqueColors.withIndex()) {
val u = (index.toDouble() / uniqueColors.size + (1.0 / uniqueColors.size / 2.0)).toFloat()
val v = 0.5f
val texIndex = cacheUV(u, v)
colorTexCoordsMap[color] = texIndex
atlas.pixelWriter.setColor(index, 0, color)
}