port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,513 @@
-------------------------------------------------------------------------------------
utility bluExport "BluFlame v0.2 Export"
(
-- Define variables that are visible to all functions in the utility
local ostream, tabs = ""
local version = 2
local usedMaterials = #()
-- Define the GUI interface
group "Options"
(
checkbox cb_exportSelOnly "Export Selected Only"
)
button btn_export "Save As..." width:100
------------------------------------------------------------------------------------
function computeTangent obj =
(
local theMesh = snapshotAsMesh obj
local tSpace = #()
-- Do we have to flip faces?
local flip = false
local indices = #(1, 2, 3)
if dot (cross obj.transform.row1 obj.transform.row2) obj.transform.row3 <= 0 do
(
indices[2] = 3
indices[3] = 2
flip = true
)
for nFace = 1 to theMesh.numFaces do
(
local face = getFace theMesh nFace
local tface = getTVFace theMesh nFace
local v1 = getVert theMesh face[indices[1]]
local v2 = getVert theMesh face[indices[2]]
local v3 = getVert theMesh face[indices[3]]
local uv1 = getTVert theMesh tface[indices[1]]
local uv2 = getTVert theMesh tface[indices[2]]
local uv3 = getTVert theMesh tface[indices[3]]
local dV1 = v1 - v2
local dV2 = v1 - v3
local dUV1 = uv1 - uv2
local dUV2 = uv1 - uv3
local area = dUV1.x * dUV2.y - dUV1.y * dUV2.x
local sign = if area < 0 then -1 else 1
local tangent = [0,0,1]
tangent.x = dV1.x * dUV2.y - dUV1.y * dV2.x
tangent.y = dV1.y * dUV2.y - dUV1.y * dV2.y
tangent.z = dV1.z * dUV2.y - dUV1.y * dV2.z
tangent = (normalize tangent) * sign
append tSpace tangent
)
delete theMesh
return tSpace
)
function AddMaterialToList inmaterial =
(
local canadd = true
for mat in usedMaterials do
(
if mat == inmaterial then
(
canadd = false
break
)
)
if canadd then
(
append usedMaterials inmaterial
)
)
-------------------------------------------------------------------------------------
-- This function exports a bones object to the BLU file.
function ExportNodeAnimation node =
(
-- animation header
writelong ostream 3 -- 3: animation
writestring ostream node.name
-- position
writelong ostream node.position.controller.keys.count #unsigned
for i = 1 to node.position.controller.keys.count do
(
writefloat ostream (node.position.controller.keys[i].time / 30.0)
if node.parent != undefined then
trans = in coordsys node.parent [node.pos.x_position.controller.keys[i].value, node.pos.y_position.controller.keys[i].value, node.pos.z_position.controller.keys[i].value]
else
trans = in coordsys world [node.pos.x_position.controller.keys[i].value, node.pos.y_position.controller.keys[i].value, node.pos.z_position.controller.keys[i].value]
writefloat ostream trans.x
writefloat ostream trans.y
writefloat ostream trans.z
)
-- scale
writelong ostream node.scale.controller.keys.count #unsigned
for i = 1 to node.scale.controller.keys.count do
(
writefloat ostream (node.scale.controller.keys[i].time / 30.0)
writefloat ostream node.scale.controller.keys[i].value.x
writefloat ostream node.scale.controller.keys[i].value.y
writefloat ostream node.scale.controller.keys[i].value.z
)
-- rotation
writelong ostream node.rotation.controller.keys.count #unsigned
for i = 1 to node.rotation.controller.keys.count do
(
writefloat ostream (node.rotation.controller.keys[i].time / 30.0)
writefloat ostream node.rotation.x_rotation.controller.keys[i].value
writefloat ostream node.rotation.y_rotation.controller.keys[i].value
writefloat ostream node.rotation.z_rotation.controller.keys[i].value
)
)
-------------------------------------------------------------------------------------
-- This function exports a bones object to the BLU file.
function ExportBone bone =
(
-- bone header
writelong ostream 2 -- 2: bone
writestring ostream bone.name
if bone.parent != undefined then
writestring ostream bone.parent.name
else
writestring ostream ""
-- Translation (IN PARENT SPACE)--
if bone.parent != undefined then
trans = in coordsys parent at time 0.0 bone.pos
else
trans = in coordsys world at time 0.0 bone.pos
writefloat ostream trans.x
writefloat ostream trans.y
writefloat ostream trans.z
print "bone:"
print trans
-- Rotation (IN PARENT SPACE)--
rot = in coordsys parent bone.rotation at time 0.0
writefloat ostream rot.x
writefloat ostream rot.y
writefloat ostream rot.z
writefloat ostream rot.w
-- Scale --
sca = bone.scale at time 0.0
writefloat ostream sca.x
writefloat ostream sca.y
writefloat ostream sca.z
)
-------------------------------------------------------------------------------------
-- This function exports a material object to the BLU file.
function ExportMaterial mat =
(
-- material header
writelong ostream 1 -- 1: material
writestring ostream mat.name
if classof mat.diffusemap == Bitmaptexture and mat.diffuseMapenable then
writestring ostream mat.diffuseMap.bitmap.filename
else
writestring ostream ""
if classof mat.specularmap == Bitmaptexture and mat.specularmapenable then
writestring ostream mat.specularmap .bitmap.filename
else
writestring ostream ""
if classof mat.bumpmap == Bitmaptexture and mat.bumpmapenable then
writestring ostream mat.bumpmap .bitmap.filename
else
writestring ostream ""
if classof mat.SelfIllumMap == Bitmaptexture and mat.SelfIllumMapenable then
writestring ostream mat.SelfIllumMap.bitmap.filename
else
writestring ostream ""
if classof mat.reflectionmap == Bitmaptexture and mat.reflectionmapenable then
writestring ostream mat.reflectionmap.bitmap.filename
else
writestring ostream ""
writefloat ostream mat.ambient.r
writefloat ostream mat.ambient.g
writefloat ostream mat.ambient.b
writefloat ostream mat.ambient.a
writefloat ostream mat.diffuse.r
writefloat ostream mat.diffuse.g
writefloat ostream mat.diffuse.b
writefloat ostream mat.diffuse.a
writefloat ostream mat.specular.r
writefloat ostream mat.specular.g
writefloat ostream mat.specular.b
writefloat ostream mat.specular.a
if (mat.selfIllumAmount > 0) then
(
writefloat ostream mat.selfIllumAmount
writefloat ostream mat.selfIllumAmount
writefloat ostream mat.selfIllumAmount
writefloat ostream mat.selfIllumAmount
)
else
(
writefloat ostream mat.selfIllumColor.r
writefloat ostream mat.selfIllumColor.g
writefloat ostream mat.selfIllumColor.b
writefloat ostream mat.selfIllumColor.a
)
writefloat ostream mat.specularlevel
writefloat ostream mat.glossiness
)
-------------------------------------------------------------------------------------
-- This function exports a geometry object to the BLU file.
function ExportMesh node meshObj name =
(
local isSkin = (node.modifiers["skin"] != undefined)
if isSkin then
(
max modify mode
modPanel.setCurrentObject node.modifiers["skin"]
)
-- mesh header
writelong ostream 0 -- 0: mesh
writestring ostream name
if meshObj.material != undefined then
(
writestring ostream meshObj.material.name
AddMaterialToList meshObj.material
)
else
(
writestring ostream ""
)
-- vertex count
writelong ostream meshObj.numVerts #unsigned
-- vertex elements
-- 0: Position2D
-- 1: Position3D
-- 2: Position4D
-- 3: Normal
-- 4: ColorRGB
-- 5: ColorARGB
-- 6: ColorRGBf
-- 7: ColorARGBf
-- 8: Texture2D
-- 9: Texture3D
-- 10: Texture4D
-- 11: Tangent3D
-- 12: Tangent4D
-- 13: BlendIndices
-- 14: BlendWeights
local numVElements = 3
if meshObj.material != undefined and meshObj.material.bumpmapenable then
numVElements += 1
if isSkin then
numVElements += 2 -- blendindicies and weights
writelong ostream numVElements -- number of vertexelements
writelong ostream 1
writelong ostream 3
writelong ostream 8
PerFaceTangents = #()
if meshObj.material != undefined and meshObj.material.bumpmapenable then
(
writelong ostream 11 -- tangent
PerFaceTangents = computeTangent meshObj
)
if isSkin then
(
writelong ostream 13 -- BlendIndices
writelong ostream 14 -- BlendWeights
)
local hasTooMuchBonesPerVertex = false
for i = 1 to meshObj.numVerts do
(
vert = ((GetVert meshObj i)-meshObj.pos)
writefloat ostream vert.x
writefloat ostream vert.y
writefloat ostream vert.z
normal = GetNormal meshObj i
writefloat ostream normal.x
writefloat ostream normal.y
writefloat ostream normal.z
uvw = GetTVert meshObj i
writefloat ostream uvw.x
writefloat ostream uvw.y
-- tangent
if meshObj.material != undefined and meshObj.material.bumpmapenable then
(
local vertfaces = meshop.getFacesUsingVert meshObj #{i}
local tangent = 0;
for face in vertfaces do
(
tangent += PerFaceTangents[face]
)
tangent = (normalize tangent)
writefloat ostream tangent.x
writefloat ostream tangent.y
writefloat ostream tangent.z
)
if isSkin then
(
local bone_idA = 0
local weightA = 0.0
local bone_idB = 0
local weightB = 0.0
local bone_idC = 0
local weightC = 0.0
local bone_idD = 0
local weightD = 0.0
if (skinops.getVertexWeightCount node.skin i > 0) then
(
local bone_idA = skinops.getVertexWeightBoneID node.skin i 1
local weightA = skinops.getVertexWeight node.skin i 1
)
if (skinops.getVertexWeightCount node.skin i > 1) then
(
local bone_idB = skinops.getVertexWeightBoneID node.skin i 2
local weightB = skinops.getVertexWeight node.skin i 2
)
if (skinops.getVertexWeightCount node.skin i > 2) then
(
local bone_idC = skinops.getVertexWeightBoneID node.skin i 3
local weightC = skinops.getVertexWeight node.skin i 3
)
if (skinops.getVertexWeightCount node.skin i > 3) then
(
local bone_idD = skinops.getVertexWeightBoneID node.skin i 4
local weightD = skinops.getVertexWeight node.skin i 4
)
if (skinops.getVertexWeightCount node.skin i > 4) then
hasTooMuchBonesPerVertex = true
writefloat ostream (bone_idA - 1)
writefloat ostream (bone_idB - 1)
writefloat ostream (bone_idC - 1)
writefloat ostream (bone_idD - 1)
writefloat ostream weightA
writefloat ostream weightB
writefloat ostream weightC
writefloat ostream weightD
)
)
writelong ostream (meshObj.numFaces * 3) #unsigned
for i = 1 to meshObj.numFaces do
(
poly = GetFace meshObj i
writelong ostream (poly.x as integer -1) #unsigned
writelong ostream (poly.y as integer -1) #unsigned
writelong ostream (poly.z as integer -1) #unsigned
)
if hasTooMuchBonesPerVertex then
MessageBox (name + " has too much bones per vertex.")
)
-------------------------------------------------------------------------------------
-- This function is called once per node in the scene.
-- A node in Max may be all sorts of things. We are only interested in geometry.
function ExportNode node =
(
-- Create node and export class specific data
if SuperClassOf node == GeometryClass and ClassOf node == BoneGeometry then
(
ExportBone node
)
else if SuperClassOf node == GeometryClass and ClassOf node == Editable_mesh then
(
ExportMesh node node node.name
)
else if SuperClassOf node == GeometryClass then
(
-- Build a mesh out of this object and save it
local temp = copy node
convertToMesh temp
if SuperClassOf temp == GeometryClass and ClassOf temp == Editable_mesh then
(
ExportMesh node temp node.name
)
delete temp
)
else -- Not geometry.. could be a camera, light, etc.
return false
if (node.position.controller.keys.count > 0 or
node.scale.controller.keys.count > 0 or
node.rotation.controller.keys.count > 0) then
(
ExportNodeAnimation node
)
return true
)
-------------------------------------------------------------------------------------
-- This function recurses down the node hierarchy calling ExportNode for each node.
function RecursiveExportNode node =
(
if (ExportNode node) == false then
return false
-- Recurse children before writing this node
for child in node.children do
RecursiveExportNode child
)
-------------------------------------------------------------------------------------
-- The highest level function called to export an BLU file.
function ExportBLU =
(
-- Write the BLU header
writestring ostream "BLUF"
writelong ostream version
if cb_exportSelOnly.checked then
(
for node in selection do
ExportNode node
)
else
(
for node in rootnode.children do
RecursiveExportNode node
)
for mat in usedMaterials do
(
ExportMaterial mat
)
)
-------------------------------------------------------------------------------------
-- Open an prepare a file handle for writing.
function GetSaveFileStream =
(
fname = GetSaveFileName types:"BLU (*.blu)|*.blu|All Files(*.*)|*.*|"
if fname == undefined then
return undefined
ostream = fopen fname "wbS" -- CreateFile fname
if ostream == undefined then
(
MessageBox "Couldn't open file for writing!"
return undefined
)
return ostream
)
-------------------------------------------------------------------------------------
-- This is the function called when the user activates the utility by pressing on
-- the export button. It opens the file and calls the export routine.
on btn_export pressed do
(
ostream = GetSaveFileStream()
if ostream != undefined then
(
ExportBLU()
fclose ostream
)
)
) -- End BLUExport