592 lines
16 KiB
Plaintext
Executable File
592 lines
16 KiB
Plaintext
Executable File
-- Required for building fragment-proxys:
|
|
filein "pipeline/export/maps/mapsetup.ms"
|
|
|
|
|
|
|
|
struct RsPropRenderSettings
|
|
(
|
|
buildFragsBool=undefined,
|
|
p4checkoutBool=undefined,
|
|
syncTexturesBool=undefined,
|
|
renderOutputPath=undefined,
|
|
renderStandardBool=undefined,
|
|
renderScaleObjectBool=undefined,
|
|
renderAngle=undefined,
|
|
minCamZoom = undefined,
|
|
jpgQualitySetting =undefined,
|
|
|
|
batchMode = false
|
|
)
|
|
|
|
struct RsPropRenderUtils
|
|
(
|
|
fn GenerateAndSaveImages filename renderSmall:false edgeFaces:false ThumbSize:[640,480] RatioDiff:1.0 =
|
|
(
|
|
clearSelection()
|
|
|
|
-- Large img
|
|
viewport.setShowEdgeFaces edgeFaces
|
|
redrawviews()
|
|
img = gw.getViewportDib()
|
|
img.filename = filename
|
|
save img
|
|
-- format "Render: %\n" (RsMakeBackSlashes filename)
|
|
|
|
if (RatioDiff != 1.0) do
|
|
(
|
|
local tempTexture = bitmapTexture bitmap:img
|
|
|
|
case of
|
|
(
|
|
(RatioDiff > 1):
|
|
(
|
|
tempTexture.coords.U_Tiling /= RatioDiff
|
|
)
|
|
(RatioDiff < 1):
|
|
(
|
|
tempTexture.coords.V_Tiling *= RatioDiff
|
|
)
|
|
)
|
|
|
|
img = renderMap tempTexture size:ThumbSize filter:False
|
|
img.filename = filename
|
|
save img
|
|
)
|
|
|
|
-- Small img
|
|
if renderSmall do
|
|
(
|
|
smallImg = bitmap (ThumbSize.X / 2) (ThumbSize.Y / 2)
|
|
copy img smallImg
|
|
smallImg.filename = (getFilenamePath filename) + (getFilenameFile filename) + "_Small.jpg"
|
|
-- format "Render: %\n" smallImg.filename
|
|
save smallImg
|
|
close smallImg
|
|
)
|
|
|
|
close img
|
|
),
|
|
|
|
--
|
|
-- fn: GetObjDimensions
|
|
-- desc: Returns the object's dimensions
|
|
--
|
|
fn GetObjDimensions obj bb =
|
|
(
|
|
widthX = bb[2].x - bb[1].x
|
|
lengthY = bb[2].y - bb[1].y
|
|
heightZ = bb[2].z - bb[1].z
|
|
|
|
-- Incase these come out negative, make them positive
|
|
if (widthX < 0 ) do
|
|
(
|
|
widthX *= -1
|
|
)
|
|
if (lengthY < 0 ) do
|
|
(
|
|
lengthY *= -1
|
|
)
|
|
if (heightZ < 0 ) do
|
|
(
|
|
heightZ *= -1
|
|
)
|
|
|
|
objDim = Point3 widthX lengthY heightZ
|
|
),
|
|
|
|
fn getObjRadius obj objCentre xyRadius:false=
|
|
(
|
|
-- Get the max radius of the object:
|
|
local centreOffset = objCentre - obj.pos - obj.objectoffsetpos
|
|
|
|
if xyRadius do
|
|
(
|
|
centreOffset.z = 0
|
|
)
|
|
|
|
local objMesh = copy obj.mesh
|
|
|
|
local objRadius = 0.0
|
|
local vertPos, vertDist
|
|
for vert in objMesh.verts do
|
|
(
|
|
vertPos = vert.pos
|
|
if xyRadius do (vertPos.z = 0)
|
|
|
|
vertDist = distance (vertPos * obj.scale) centreOffset
|
|
if (vertDist > objRadius) do (objRadius = vertDist)
|
|
)
|
|
|
|
objRadius
|
|
),
|
|
|
|
--
|
|
-- fn: PositionScaleObj
|
|
-- desc: Places the scale-object (i.e. standing human) depending on the size of the object being rendered
|
|
--
|
|
fn PositionScaleObj ScaleObj objDim objCentre ScaleObjDim ScaleObjRadius camAngle=
|
|
(
|
|
ScaleObj.isHidden = false
|
|
ScaleObj.wirecolor = case of
|
|
(
|
|
-- Object is shown as pink if object is over 10 units
|
|
(objDim.z >= 10):(color 255 64 200)
|
|
-- Yellow if between 2 and 10 units
|
|
(objDim.z >= 2):(color 200 200 32)
|
|
-- Green if smaller than 2 units
|
|
Default:(color 0 128 0)
|
|
)
|
|
|
|
ScaleObj.pos = objCentre
|
|
|
|
-- The origin isn't consistent for all objects - some have their z origin in their centre
|
|
-- so make sure the ScaleObj is 'standing' at same level as the prop is, rather than just
|
|
-- relying on the origin to always start on the 'ground' plane
|
|
ScaleObj.pos.z = objCentre.z - (objDim.z / 2)
|
|
|
|
local posMults = #([1,1,0],[1,-1,0],[-1,-1,0],[-1,1,0])
|
|
|
|
local posMultNum = case of
|
|
(
|
|
(camAngle == (eulerAngles 0 0 90)):1
|
|
(camAngle == (eulerAngles 0 0 0)):2
|
|
(camAngle == (eulerAngles 0 0 180)):3
|
|
(camAngle == (eulerAngles 0 0 -90)):4
|
|
)
|
|
|
|
-- If obj is longer (x axis) than longer (y axis), put ScaleObj in front/behind
|
|
-- Otherwise, put ScaleObj to left of object
|
|
local posMult = if (objDim.x < objDim.y) then posMults[posMultNum]
|
|
else
|
|
(
|
|
if (objDim.z > ScaleObjDim.z) then
|
|
(
|
|
posMultNum -= 1
|
|
)
|
|
else
|
|
(
|
|
posMultNum += 1
|
|
)
|
|
posMultNum = mod posMultNum 4
|
|
if (posMultNum == 0) do (posMultNum = 4)
|
|
|
|
posMult = posMults[posMultNum] * [0,1,0]
|
|
)
|
|
|
|
ScaleObj.pos += (posMult * (ScaleObjRadius + (objDim / 2)))
|
|
),
|
|
|
|
-- this should be called directly after creating the camera, but before you transform the camera at all... it is a simple setup.
|
|
fn placeTextInRender parentCamera renderTextString=
|
|
(
|
|
local placedTextObj = text size:0.25 text:renderTextString render_renderable:true wirecolor:[255,0,0] pos:parentCamera.target.pos render_thickness:0.05
|
|
rotate placedTextObj (eulerAngles 90 0 90)
|
|
move placedTextObj [-10, 0, -2.5]
|
|
placedTextObj.parent = parentCamera
|
|
|
|
),
|
|
|
|
|
|
-- This needs to be extended to work from a settings file in the future. for now it is hard coded
|
|
fn generateTextFlags filepath=
|
|
(
|
|
local textFlag = undefined
|
|
local pathCases = #(datapair name:"lev_des" value:"DESIGN ONLY", datapair name:"areas" value:"AREA FILE TEST")
|
|
|
|
for pattern in pathCases do
|
|
(
|
|
if (matchpattern (toLower filepath) pattern:("*" + pattern.name + "*")) then
|
|
(
|
|
if textFlag == undefined then
|
|
(
|
|
textFlag = pattern.value
|
|
)
|
|
else
|
|
(
|
|
textFlag = textFlag + ", " + pattern.value
|
|
)
|
|
)
|
|
)
|
|
textFlag
|
|
),
|
|
|
|
--
|
|
-- fn: SetupCamera
|
|
-- desc: Returns a camera and sets the viewport to use it for the render
|
|
--
|
|
fn SetupCamera cam objCentre objRadius camDistanceFactor camMinZoom camAngle =
|
|
(
|
|
if (objRadius < camMinZoom) do -- Set minimum object-size for zooming:
|
|
(
|
|
objRadius = camMinZoom
|
|
)
|
|
|
|
local camDirMult = case of
|
|
(
|
|
( camAngle == (eulerAngles 0 0 90)):[-1,1,1]
|
|
(camAngle == (eulerAngles 0 0 0)):[1,1,1]
|
|
(camAngle == (eulerAngles 0 0 180)):[-1,-1,1]
|
|
(camAngle == (eulerAngles 0 0 -90)):[1,-1,1] -- Default direction
|
|
)
|
|
|
|
cam.target.pos = objCentre
|
|
cam.fovType = 1
|
|
|
|
local camDistance = (objRadius * 1.0) / (tan (0.5 * cam.curFOV))
|
|
|
|
cam.pos = objCentre + (camDirMult * camDistance * camDistanceFactor)
|
|
|
|
cam.clipManually = true
|
|
cam.nearclip = 0.0
|
|
viewport.setcamera cam
|
|
|
|
|
|
cam
|
|
),
|
|
|
|
|
|
|
|
--
|
|
-- fn: RenderSelected
|
|
-- desc: Render selected objects out to network drive, two images.
|
|
-- One rendered textured, another with edged faces and a standing-human scale-object.
|
|
--
|
|
--fn RenderObjs objs buildFrags:chkRebuildFrags.checked p4checkout:chkPerforce.checked syncTextures:chkSyncTextures.checked =
|
|
fn RenderObjs objs settingsObject quiet:true ThumbSize:[640,480] =
|
|
(
|
|
|
|
local modelsDir = RsConfigGetModelSourceDir()
|
|
local modelsDirCount = modelsDir.count
|
|
|
|
local currentPath = RsMakeSafeSlashes (maxfilePath + (getFilenameFile maxfileName))
|
|
print ("Cur Path:" + currentPath)
|
|
|
|
if not (matchPattern currentPath pattern:(modelsDir + "*")) do
|
|
(
|
|
messageBox ("Can't render props - Maxfile must be saved under:\n\n" + modelsDir) title:"Error: Invalid Maxfile path"
|
|
return false
|
|
)
|
|
local textFlag = generateTextFlags currentPath --used to generate text in the render
|
|
--print ("TEXTFLAGS:" + textFlag)
|
|
|
|
local exportPath = RsMakeSafeSlashes (settingsObject.renderOutputPath + "/" + (substring currentPath modelsDirCount -1) + "/")
|
|
RsMakeSurePathExists exportPath
|
|
|
|
if settingsObject.buildFragsBool do
|
|
(
|
|
gRsMapExportFragments.preExportRename()
|
|
gRsMapExportFragments.buildAllFragments silent:true objs:objs
|
|
gRsMapExportFragments.postExportRename()
|
|
)
|
|
|
|
-- Filter objs down to what we're actually going to render
|
|
local doObjs = for obj in objs where (isValidNode obj) collect
|
|
(
|
|
local useObj = obj
|
|
local isFragProxy = False
|
|
|
|
-- If this is a frag object, render its proxy
|
|
if (matchpattern obj.name pattern:"*_frag_") do
|
|
(
|
|
local fragProxy = getNodeByName (substring obj.name 1 (obj.name.count - 6))
|
|
useObj = fragProxy
|
|
|
|
if (useObj != undefined) do
|
|
(
|
|
isFragProxy = True
|
|
)
|
|
)
|
|
|
|
if
|
|
(
|
|
-- Only render for Gta Objects:
|
|
(GetAttrClass useObj == "Gta Object") and
|
|
|
|
-- Don't render if object-parent is geometry too:
|
|
(GetAttrClass useObj.parent != "Gta Object") and
|
|
|
|
-- Don't render for X/RsRefs:
|
|
(not isRefObj useObj) and
|
|
|
|
-- Don't render thumbs for objects with SceneLink children: (i.e. LODs of all kinds)
|
|
(
|
|
local getObjs = #()
|
|
RsSceneLink.GetChildren -1 obj &getObjs
|
|
(getObjs.count == 0)
|
|
) and
|
|
|
|
-- Don't render "Dont Export" geometry, unless it's a Frag Proxy:
|
|
(isFragProxy or ((GetAttr useObj (GetAttrIndex "Gta Object" "Dont Export")) != true))
|
|
)
|
|
then useObj else dontCollect
|
|
)
|
|
|
|
-- Pre-generate the object-filenames:
|
|
local renderFiles = #()
|
|
local defaultFilenames = #()
|
|
local scaleFilenames = #()
|
|
|
|
for obj in doObjs do
|
|
(
|
|
local filenameStart = exportPath + obj.name
|
|
|
|
if settingsObject.renderStandardBool do
|
|
(
|
|
append defaultFilenames (filenameStart + ".jpg")
|
|
)
|
|
if settingsObject.renderScaleObjectBool do
|
|
(
|
|
append scaleFilenames (filenameStart + "_Jaxx.jpg")
|
|
)
|
|
)
|
|
|
|
local renderFiles = #()
|
|
join renderFiles defaultFilenames
|
|
join renderFiles scaleFilenames
|
|
|
|
-- Exit if no files are to be rendered:
|
|
if (renderFiles.count == 0) do
|
|
(
|
|
return true
|
|
)
|
|
|
|
if settingsObject.p4checkoutBool do
|
|
(
|
|
-- Perforce-add/edit all render-files:
|
|
pushPrompt "Preparing Perforce for export"
|
|
local perforceSuccess = gRsPerforce.add_or_edit renderFiles queueAdd:true
|
|
popPrompt()
|
|
|
|
if (not perforceSuccess) and (queryBox "Problems were encountered accessing Perforce.\nCancel render?" title:"Prop Render: Perforce Errors") do
|
|
(
|
|
return false
|
|
)
|
|
)
|
|
|
|
if settingsObject.syncTexturesBool do
|
|
(
|
|
local matsUsed = #()
|
|
for obj in doObjs do
|
|
(
|
|
local objMats = RsGetMaterialsOnObjFaces obj
|
|
join matsUsed objMats
|
|
)
|
|
|
|
local textureList = #()
|
|
for mat in (makeUniqueArray matsUsed) do
|
|
(
|
|
RsGetMaterialTextures mat textureList:textureList
|
|
)
|
|
|
|
RsP4syncTextures textureList
|
|
)
|
|
|
|
undo off
|
|
(
|
|
-- Changing render-options is slow when Diplay panel is up, so this'll speed it up:
|
|
max create mode
|
|
|
|
-- Remember which things were hidden/shown
|
|
local selectionWas = selection as array
|
|
local objectsWas = objects as array
|
|
local hiddenWas = for obj in objectsWas collect obj.isHidden
|
|
for object in objects do (object.isHidden = true)
|
|
|
|
local activeViewport = viewport.activeViewport
|
|
local gridVisWas = viewport.getGridVisibility activeViewport
|
|
viewport.setGridVisibility #all false
|
|
|
|
local renderLevelWas = viewport.getRenderLevel()
|
|
viewport.setRenderLevel #smoothhighlights
|
|
|
|
local jpegQualityWas = jpeg.getQuality()
|
|
jpeg.setQuality settingsObject.jpgQualitySetting
|
|
|
|
local BGColorWas = getUIColor 41
|
|
setUIColor 41 [0.49,0.49,0.49]
|
|
|
|
local displayColorWireframeWas = displayColor.wireframe
|
|
local displayColorShadedWas = displayColor.shaded
|
|
displayColor.wireframe = #object
|
|
displayColor.shaded = #material
|
|
|
|
local edgeFacesWas = viewport.getShowEdgeFaces()
|
|
local viewCamWas = getActiveCamera()
|
|
local viewTypeWas = viewport.getType()
|
|
viewport.setType #view_persp_user
|
|
local viewTMWas = viewport.getTM()
|
|
local fovWas = viewport.getFOV()
|
|
local focalWas = viewport.getFocalDistance()
|
|
|
|
local windowSizeWas = [gw.getWinSizeX(), gw.getWinSizeY()]
|
|
local camDistanceFactor = 1.1
|
|
|
|
-- Set viewport size/shape:
|
|
local currentSizeRatio = (windowSizeWas.X / windowSizeWas.Y)
|
|
local ThumbSizeRatio = (ThumbSize.X / ThumbSize.Y)
|
|
local RatioDiff = (currentSizeRatio / ThumbSizeRatio)
|
|
local newViewSize = ThumbSize
|
|
|
|
case of
|
|
(
|
|
(RatioDiff > 1):
|
|
(
|
|
newViewSize = [ThumbSize.X * RatioDiff, ThumbSize.Y]
|
|
camDistanceFactor *= RatioDiff
|
|
)
|
|
(RatioDiff < 1):
|
|
(
|
|
newViewSize = [ThumbSize.X, ThumbSize.Y / RatioDiff]
|
|
)
|
|
)
|
|
--format "%, % : %\n" currentSizeRatio ThumbSizeRatio newViewSize
|
|
|
|
gw.setPos 0 0 newViewSize.X newViewSize.Y
|
|
|
|
-- If the viewcube or stats is visible, turn it off for renders.
|
|
-- Turned back on at end, if it was visible before this script was called.
|
|
local viewCubeWas
|
|
if (ViewCubeOps != undefined) do
|
|
(
|
|
viewCubeWas = ViewCubeOps.Visibility
|
|
ViewCubeOps.Visibility = false
|
|
)
|
|
|
|
popPrompt()
|
|
local cam = TargetCamera target:(TargetObject())
|
|
|
|
if textFlag != undefined then
|
|
(
|
|
placeTextInRender cam textFlag -- add text into the render...
|
|
)
|
|
|
|
local ScaleObj = undefined
|
|
local copyObj = undefined
|
|
|
|
-- try
|
|
(
|
|
progressStart "Rendering objects:"
|
|
format "Rendering % objects to \"%\"\n%\n" doObjs.count exportPath (doObjs as string)
|
|
|
|
-- Create scale-object:
|
|
ScaleObj = P_Standing()
|
|
local ScaleObjBB = nodeLocalBoundingBox ScaleObj
|
|
local ScaleObjDim = GetObjDimensions ScaleObj ScaleObjBB
|
|
local ScaleObjRadius = 0.45 --getObjRadius ScaleObj [0,0,0] xyRadius:true
|
|
local ScaleObjRot = settingsObject.renderAngle
|
|
|
|
rotate ScaleObj ScaleObjRot
|
|
|
|
for objNum = 1 to doObjs.count while (progressupdate ((100.0 * objNum) / doObjs.count)) do
|
|
(
|
|
local obj = doObjs[objNum]
|
|
|
|
local bb = nodeLocalBoundingBox obj
|
|
local objCentre = (bb[1]+ bb[2]) / 2
|
|
local objDim = GetObjDimensions obj bb
|
|
|
|
local objRadius = getObjRadius obj objCentre
|
|
|
|
cam = SetupCamera cam objCentre objRadius camDistanceFactor settingsObject.minCamZoom settingsObject.renderAngle
|
|
|
|
filenameConcat = exportPath + obj.name
|
|
|
|
-- Show object:
|
|
obj.isHidden = false
|
|
|
|
-- Make inverted copy, to make up for lack of 2-sidedness in some shaders:
|
|
copyObj = copy obj
|
|
copyObj.name += "_TEMPCOPY"
|
|
addModifier copyObj (Mesh_Select())
|
|
addModifier copyObj (Normalmodifier flip:true)
|
|
|
|
select obj
|
|
|
|
-- Render default image:
|
|
if settingsObject.renderStandardBool do
|
|
(
|
|
ScaleObj.isHidden = true
|
|
GenerateAndSaveImages defaultFilenames[objNum] edgeFaces:false ThumbSize:ThumbSize RatioDiff:RatioDiff
|
|
)
|
|
|
|
-- Render scale-object image
|
|
if settingsObject.renderScaleObjectBool do
|
|
(
|
|
ScaleObj.isHidden = false
|
|
scaleFilename = scaleFilenames[objNum]
|
|
|
|
PositionScaleObj ScaleObj objDim objCentre ScaleObjDim ScaleObjRadius settingsObject.renderAngle
|
|
select #(obj, ScaleObj)
|
|
GenerateAndSaveImages scaleFilename edgeFaces:true ThumbSize:ThumbSize RatioDiff:RatioDiff
|
|
)
|
|
|
|
delete copyObj
|
|
|
|
-- Hide object again for now
|
|
obj.isHidden = true
|
|
)
|
|
)
|
|
-- catch
|
|
(
|
|
-- format "Exception caught while rendering the props:\n%\n" (getCurrentException())
|
|
)
|
|
|
|
progressEnd()
|
|
|
|
for TempObj in #(Cam, ScaleObj, CopyObj) do
|
|
(
|
|
if (isValidNode TempObj) do
|
|
(
|
|
delete TempObj
|
|
)
|
|
)
|
|
|
|
pushPrompt "Restoring viewport settings"
|
|
-- Revert object-hidden states
|
|
for n = 1 to objectsWas.count do
|
|
(
|
|
objectsWas[n].isHidden = hiddenWas[n]
|
|
)
|
|
|
|
clearSelection()
|
|
select selectionWas
|
|
|
|
-- Revert viewport settings
|
|
gw.setPos 0 0 windowSizeWas.X windowSizeWas.Y
|
|
|
|
viewport.setFocalDistance focalWas
|
|
viewport.setFOV fovWas
|
|
viewport.setTM viewTMWas
|
|
viewport.setType viewTypeWas
|
|
|
|
viewport.setGridVisibility activeViewport gridVisWas
|
|
viewport.setRenderLevel renderLevelWas
|
|
viewport.setShowEdgeFaces edgeFacesWas
|
|
|
|
displayColor.wireframe = displayColorWireframeWas
|
|
displayColor.shaded = displayColorShadedWas
|
|
|
|
setUIColor 41 BGColorWas
|
|
|
|
jpeg.setQuality jpegQualityWas
|
|
|
|
if (viewCubeWas != undefined) do
|
|
(
|
|
ViewCubeOps.Visibility = viewCubeWas
|
|
)
|
|
popPrompt()
|
|
)
|
|
|
|
-- Add queued files to Perforce, if any:
|
|
gRsPerforce.postExportAdd showProgress:showProgress
|
|
|
|
if quiet == false then
|
|
(
|
|
messageboxmessage = "Successfully rendered " + doObjs.count as string + " objects."
|
|
messagebox messageboxmessage title:"Render Finished" beep:false
|
|
)
|
|
setFocus RsRenderPropsRoll
|
|
|
|
return true
|
|
)
|
|
) |