276 lines
8.9 KiB
Plaintext
Executable File
276 lines
8.9 KiB
Plaintext
Executable File
-- Data structures
|
|
TBCPV_UVimageOutputSize = #(256,512,1024)
|
|
TBCPV_paddingSizeArray = #(16,10,4)
|
|
|
|
-- Dump textures to here, this is for debug only
|
|
TBCPV_outputTextureFolder = RsConfigGetWildWestDir() + "assets/texture_based_data/texture_based_CPV"
|
|
|
|
-- Struct to hold vertex index, its colour, and its uv coords
|
|
struct RsTa_cpvVertData
|
|
(
|
|
vertMeshIndex = undefined,
|
|
vertCPVColour = undefined,
|
|
vertUVArray = #()
|
|
)
|
|
|
|
|
|
|
|
-- Function that collects all the map/UV verts from the mesh verts
|
|
-- Returns data as an array where each index corresponds to the mesh index
|
|
-- Save the UV coordinate too
|
|
fn RsTa_TBCPV_meshVertToUVVert meshobj UVChannel =
|
|
(
|
|
|
|
-- Work on a mesh version of the geometry
|
|
local tempMesh = snapshotasmesh meshobj
|
|
local numMeshFaces = tempMesh.numFaces
|
|
|
|
local UVMappingArray = #()
|
|
|
|
-- Run through the mesh and collect the UV data for each face
|
|
-- Each triangle will have 3 verts, so 3 values will be returned
|
|
startTime = timeStamp()
|
|
for faceIndex=1 to numMeshFaces do
|
|
(
|
|
theMeshFace = getFace tempMesh faceIndex
|
|
theTFace = getTVFace tempMesh faceIndex
|
|
|
|
-- The Mesh face has 3 points, x, y, and z
|
|
-- These correspond to the x, y and z of the tvert
|
|
-- Store the mapping plus the U, V and W of the Tvert
|
|
local VertMapping = #(theMeshFace.x as integer, theTFace.x as integer, (getTVert tempMesh theTFace.x))
|
|
append UVMappingArray VertMapping
|
|
|
|
local VertMapping = #(theMeshFace.y as integer, theTFace.y as integer, (getTVert tempMesh theTFace.y))
|
|
append UVMappingArray VertMapping
|
|
|
|
local VertMapping = #(theMeshFace.z as integer, theTFace.z as integer, (getTVert tempMesh theTFace.z))
|
|
append UVMappingArray VertMapping
|
|
)
|
|
|
|
endTime = timeStamp()
|
|
format "Collection mapping time :% seconds\n" ((endTime-startTime )/ 1000)
|
|
|
|
-- The mapping array is very full, I need to make is as small as possible
|
|
local parsedUVMappingArray = #(UVMappingArray[1])
|
|
local mappingcount = UVMappingArray.count
|
|
|
|
startTime = timeStamp()
|
|
|
|
-- Loop through the collected data, collecting any unique vert/texture vert mappings
|
|
-- This can get slow with large data sets - ~10 seconds for 3000 verts
|
|
for UVMappingArrayIndex = 2 to mappingcount do
|
|
(
|
|
-- Grab the mapped entry
|
|
local theMappingEntry = UVMappingArray[UVMappingArrayIndex]
|
|
|
|
-- Set a found flag to be false
|
|
matchfound = false
|
|
|
|
-- Check each in sequence
|
|
currentParsedCount = parsedUVMappingArray.count
|
|
for checkIndex = 1 to currentParsedCount do
|
|
(
|
|
local chkMappingEntry = parsedUVMappingArray[checkIndex]
|
|
|
|
-- Have already stored that mesh vert?
|
|
if theMappingEntry[1] == chkMappingEntry[1] then
|
|
(
|
|
-- Have we go that Texture vert too?
|
|
if theMappingEntry[2] == chkMappingEntry[2] then
|
|
(
|
|
matchfound = true
|
|
)
|
|
)
|
|
)
|
|
|
|
-- If no match is found then we want to save this data
|
|
if matchfound == false then append parsedUVMappingArray theMappingEntry
|
|
|
|
) -- End parsing
|
|
|
|
endTime = timeStamp()
|
|
format "Search time :% seconds\n" ((endTime-startTime )/ 1000)
|
|
|
|
|
|
-- Sort this parsed array to make things easier later
|
|
qsort parsedUVMappingArray sortArraybySubIndex subIndex:1
|
|
|
|
parsedUVMappingArray -- return this mapping
|
|
)
|
|
|
|
|
|
|
|
-- Collect the vert data
|
|
-- Takes an object and returns a breakdown of the verts
|
|
fn RsTa_TBCPV_CollectMeshData meshObject theObjectUVChannel =
|
|
(
|
|
-- Switch to modify mode
|
|
max modify mode
|
|
|
|
local numObjectVerts = meshObject.numVerts
|
|
|
|
-- Loop through all the verts in index order and for each vertex get its colour from channel 11
|
|
local cpvVertListData = #()
|
|
|
|
for vertIndex = 1 to numObjectVerts do
|
|
(
|
|
-- Create a struct to hold this data
|
|
RsTa_cpvVertDataInstance = RsTa_cpvVertData vertMeshIndex:vertIndex
|
|
|
|
if (classOf meshObject.baseObject == Editable_Poly) then
|
|
(
|
|
polyop.setVertSelection meshObject vertIndex
|
|
RsTa_cpvVertDataInstance.vertCPVColour = meshObject.GetVertexColor 11
|
|
)
|
|
else
|
|
(
|
|
|
|
)
|
|
|
|
append cpvVertListData RsTa_cpvVertDataInstance
|
|
) -- End vertex loop
|
|
|
|
|
|
-- Now we need to map this CPV data to the UV data
|
|
-- This will be used so that for each mesh vert I know what UV vert to use
|
|
local meshTextureVertMapping = RsTa_TBCPV_meshVertToUVVert meshObject theObjectUVChannel
|
|
-- For each vert, find the corresponsing map vert and the UV coordinate
|
|
local theCount = cpvVertListData.count
|
|
for meshVertIndex = 1 to theCount do
|
|
(
|
|
for textureVertIndex = 1 to meshTextureVertMapping.count do
|
|
(
|
|
if meshTextureVertMapping[textureVertIndex][1] == meshVertIndex then
|
|
(
|
|
append cpvVertListData[meshVertIndex].vertUVArray meshTextureVertMapping[textureVertIndex]
|
|
)
|
|
)
|
|
) -- end vertex loop
|
|
|
|
|
|
cpvVertListData -- return the collected data
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Function that creates RGB texture from the CPV colour data
|
|
fn RsTa_TBCPV_writeCPVToTexture meshObject collectedMeshData outputTextureFolder saveDataName outputTextureSize paddingSizeArray =
|
|
(
|
|
-- Make sure the folder exists
|
|
outputTextureFolder = outputTextureFolder + "/"
|
|
makeDir outputTextureFolder all:true
|
|
|
|
-- Create a texture of the specified size and fill it with black
|
|
theTextureName = meshObject.name + ".tga"
|
|
theCPVImage = bitmap outputTextureSize outputTextureSize color:black
|
|
theCPVImage.filename = outputTextureFolder + theTextureName
|
|
|
|
|
|
-- Now write the CPV colour into this texture
|
|
|
|
-- So, loop through all the verts and see if they use this bone
|
|
for theVertIndex = 1 to collectedMeshData.count do
|
|
(
|
|
local theMeshVert = collectedMeshData[theVertIndex]
|
|
|
|
-- The get the current vert's colour
|
|
local cpvColour = theMeshVert.vertCPVColour
|
|
|
|
-- Use a the padding array input parameter to add the fuzziness to the blocks
|
|
-- Create this as a new bitmap, then paste it into the bigger image
|
|
theCPVBlockRGB = bitmap paddingSizeArray[1] paddingSizeArray[1] color:cpvColour
|
|
theCPVBlockG = bitmap paddingSizeArray[2] paddingSizeArray[2] color:cpvColour
|
|
theCPVBlockB = bitmap paddingSizeArray[3] paddingSizeArray[3] color:cpvColour
|
|
|
|
g_offset = (paddingSizeArray[1] - paddingSizeArray[2])/2
|
|
b_offset = g_offset + ((paddingSizeArray[2] - paddingSizeArray[3])/2)
|
|
|
|
pasteBitmap theCPVBlockG theCPVBlockRGB (box2 0 0 paddingSizeArray[2] paddingSizeArray[2]) [g_offset, g_offset]
|
|
pasteBitmap theCPVBlockB theCPVBlockRGB (box2 0 0 paddingSizeArray[3] paddingSizeArray[2]) [b_offset, b_offset]
|
|
|
|
-- There might be multiple texture co-ordinates for the mesh vert
|
|
for tvertIndex = 1 to theMeshVert.vertUVArray.count do
|
|
(
|
|
local UVCoordinate = theMeshVert.vertUVArray[tvertIndex][3]
|
|
local paddingOffset = (paddingSizeArray[1] - 1)/2
|
|
local bitmapUVCoordinate = [((UVCoordinate.x * outputTextureSize) - paddingOffset), ((outputTextureSize - (UVCoordinate.y * outputTextureSize)) - paddingOffset)]
|
|
pasteBitmap theCPVBlockRGB theCPVImage (box2 0 0 paddingSizeArray[1] paddingSizeArray[1]) bitmapUVCoordinate
|
|
) -- end tvert loop
|
|
) -- end mesh vert loop
|
|
|
|
-- debug: display the created image
|
|
--display theCPVImage
|
|
|
|
-- Save the texture
|
|
save theCPVImage
|
|
|
|
-- Let the user know that this has worked
|
|
messagebox ("CPV texture data written to the folder " + outputTextureFolder)
|
|
|
|
)
|
|
|
|
|
|
|
|
-- Function that loads CPV colours from an image onto a mesh
|
|
fn RsTa_TBCPV_loadCPVFromTexture meshObject collectedMeshData texToLoad =
|
|
(
|
|
if collectedMeshData == undefined then
|
|
(
|
|
messagebox "There is no saved CPV data." title:"ERROR"
|
|
return false
|
|
)
|
|
|
|
pushPrompt "Loading CPV Colours..."
|
|
|
|
-- open the image and get its size
|
|
theimageFile = openBitmap texToLoad
|
|
theImageSize = theimageFile.width
|
|
|
|
local theCount = collectedMeshData.count
|
|
|
|
allstartTime = timeStamp()
|
|
for collectedVert = 1 to theCount do
|
|
(
|
|
theUVpos = collectedMeshData[collectedVert].vertUVArray[1][3]
|
|
|
|
-- Calculate the UV coordiante based on the image size
|
|
-- Bitmaps are upside down, so invert the Y
|
|
xyUV = [theUVpos.x * theImageSize, theImageSize - (theUVpos.y * theImageSize)]
|
|
|
|
thePixelColour = getPixels theimageFile xyUV 1
|
|
|
|
if (classOf meshObject.baseObject == Editable_Poly) then
|
|
(
|
|
polyOp.setVertColor meshObject 11 collectedVert thePixelColour[1]
|
|
)
|
|
else if (classOf meshObject.baseObject == Editable_mesh) then
|
|
(
|
|
meshOp.setVertColor meshObject 11 collectedVert thePixelColour[1]
|
|
)
|
|
)
|
|
|
|
allendTime = timeStamp()
|
|
format "Search time for all verts in all images was :% seconds\n" ((allendTime-allstartTime )/ 1000)
|
|
|
|
-- close the image
|
|
close theimageFile
|
|
free theimageFile
|
|
|
|
popPrompt()
|
|
print "Finished Loading Skin Weights."
|
|
messagebox "Finished Loading Skin Weights."
|
|
|
|
)
|
|
|
|
|
|
|
|
-- turns on display of the wind channel vertex colours
|
|
fn RsTa_TBCPV_setDisplayMode theObject=
|
|
(
|
|
theObject.showVertexColors = true
|
|
theObject.vertexColorsShaded = false
|
|
theObject.vertexColorType = #Map_Channel
|
|
theObject.vertexColorMapChannel = 11
|
|
) |