541 lines
17 KiB
Plaintext
Executable File
541 lines
17 KiB
Plaintext
Executable File
--
|
|
-- File:: drawablelod.ms
|
|
-- Description:: Drawable LOD Hierarchy Utility Functions
|
|
--
|
|
-- Author:: David Muir <david.muir@rockstarnorth.com>
|
|
-- Date:: 24 March 2009
|
|
--
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Uses
|
|
-----------------------------------------------------------------------------
|
|
filein "pipeline/util/drawablelod_private.ms"
|
|
filein "pipeline/util/userprops.ms"
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Globals
|
|
-----------------------------------------------------------------------------
|
|
global LinkType_LOD = 0
|
|
global LinkType_DRAWLOD = 1
|
|
global LinkType_RENDERSIM = 2
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- Functions
|
|
-----------------------------------------------------------------------------
|
|
|
|
--
|
|
-- name: RsLodDrawable_SetHigherDetailModel
|
|
-- desc: Set the higher detail mesh (model_hd) for model.
|
|
--
|
|
fn RsLodDrawable_SetHigherDetailModel model model_hd = (
|
|
|
|
if ( not RsSceneLink.HasContainer linkType_DRAWLOD model_hd ) then
|
|
RsSceneLink.AddContainer linkType_DRAWLOD model_hd
|
|
|
|
RsSceneLink.SetParent linkType_DRAWLOD model_hd model
|
|
)
|
|
|
|
|
|
--
|
|
-- name: RsLodDrawable_GetHigherDetailModel
|
|
-- desc: Get the higher detail mesh for model.
|
|
--
|
|
fn RsLodDrawable_GetHigherDetailModel model = (
|
|
|
|
local children = #()
|
|
RsSceneLink.GetChildren linkType_DRAWLOD model &children
|
|
-- print ("children:"+children as string)
|
|
if ( children.count > 0 and not isDeleted children[1]) then
|
|
( children[1] )
|
|
else
|
|
undefined
|
|
)
|
|
|
|
|
|
--
|
|
-- name: RsLodDrawable_HasHigherDetailModel
|
|
-- desc: Return whether model has a higher detail mesh assigned.
|
|
--
|
|
fn RsLodDrawable_HasHigherDetailModel model = (
|
|
local hdmodel = RsLodDrawable_GetHigherDetailModel model
|
|
return ( undefined != hdmodel and not isDeleted hdmodel )
|
|
)
|
|
|
|
|
|
--
|
|
-- name: RsLodDrawable_SetLowerDetailModel
|
|
-- desc: Set the lower detail mesh (model_ld) for model.
|
|
--
|
|
fn RsLodDrawable_SetLowerDetailModel model model_ld = (
|
|
|
|
if ( not RsSceneLink.HasContainer linkType_DRAWLOD model )
|
|
then
|
|
RsSceneLink.AddContainer linkType_DRAWLOD model
|
|
|
|
RsSceneLink.SetParent linkType_DRAWLOD model model_ld
|
|
)
|
|
|
|
|
|
--
|
|
-- name: RsLodDrawable_GetLowerDetailModel
|
|
-- desc: Get the lower detail mesh for model.
|
|
--
|
|
fn RsLodDrawable_GetLowerDetailModel model =
|
|
(
|
|
local ldmodel = RsSceneLink.GetParent linkType_DRAWLOD model
|
|
if undefined!=ldmodel and not isDeleted ldmodel then
|
|
return ldmodel
|
|
|
|
return undefined
|
|
)
|
|
|
|
|
|
--
|
|
-- name: RsLodDrawable_HasLowerDetailModel
|
|
-- desc: Return whether the model has a lower detail mesh assigned.
|
|
--
|
|
fn RsLodDrawable_HasLowerDetailModel model =
|
|
(
|
|
local ldmodel = RsSceneLink.GetParent linkType_DRAWLOD model
|
|
return (undefined != ldmodel and not isDeleted ldmodel)
|
|
)
|
|
|
|
---------------------------------------------------------------------------------------------
|
|
-- renderable child node accessors
|
|
----
|
|
|
|
--
|
|
-- name: RsLodDrawable_SetHigherDetailModel
|
|
-- desc: Set the higher detail mesh (model_hd) for model.
|
|
--
|
|
fn RsLodDrawable_SetRenderChildModel model rendermodel =
|
|
(
|
|
if ( not RsSceneLink.HasContainer LinkType_RENDERSIM rendermodel ) then
|
|
RsSceneLink.AddContainer LinkType_RENDERSIM rendermodel
|
|
if ( not RsSceneLink.HasContainer LinkType_RENDERSIM rendermodel ) then
|
|
(
|
|
messagebox "Failed adding drawable lod container to node."
|
|
)
|
|
RsSceneLink.SetParent LinkType_RENDERSIM rendermodel model
|
|
)
|
|
|
|
|
|
fn RsLodDrawable_IsRenderModel model =
|
|
(
|
|
return (RsSceneLink.HasContainer LinkType_RENDERSIM model) and (undefined!=RsSceneLink.GetParent LinkType_RENDERSIM model)
|
|
)
|
|
--
|
|
-- name: RsLodDrawable_GetHigherDetailModel
|
|
-- desc: Get the higher detail mesh for model.
|
|
--
|
|
fn RsLodDrawable_GetRenderModel model =
|
|
(
|
|
local children = #()
|
|
RsSceneLink.GetChildren LinkType_RENDERSIM model &children
|
|
if ( children.count > 0 and not isDeleted children[1])
|
|
then
|
|
return ( children[1] )
|
|
else
|
|
return ( undefined )
|
|
)
|
|
--
|
|
-- name: RsLodDrawable_GetHigherDetailModel
|
|
-- desc: Get the higher detail mesh for model.
|
|
--
|
|
fn RsLodDrawable_GetSimulationModel model =
|
|
(
|
|
if ( not RsSceneLink.HasContainer LinkType_RENDERSIM model )
|
|
then
|
|
return undefined
|
|
else
|
|
(
|
|
local simModel = RsSceneLink.GetParent LinkType_RENDERSIM model
|
|
if undefined!=simModel and not isDeleted simModel then
|
|
return simmodel
|
|
else
|
|
return undefined
|
|
)
|
|
)
|
|
|
|
--
|
|
-- name: RsLodDrawable_HasHigherDetailModel
|
|
-- desc: Return whether model has a higher detail mesh assigned.
|
|
--
|
|
fn RsLodDrawable_HasSimulationModel model = (
|
|
return (undefined != (RsLodDrawable_GetSimulationModel model))
|
|
)
|
|
|
|
--
|
|
-- name: RsLodDrawable_GetSimulationModel
|
|
-- desc: Get the parent (RENDER) mesh for model.
|
|
--
|
|
fn RsLodDrawable_HasRenderModel model =
|
|
(
|
|
return (undefined != (RsLodDrawable_GetRenderModel model))
|
|
)
|
|
|
|
fn RsLodDrawable_HasProxyModel model =
|
|
(
|
|
return (undefined != (RsSceneLink.GetParent linkType_ShadowMesh model ))
|
|
)
|
|
|
|
--
|
|
-- name: RsLodDrawable_GetShadowMeshCounterPart
|
|
-- desc: Get the model that the shadow mesh is linked to
|
|
--
|
|
fn RsLodDrawable_GetShadowMeshCounterPart model =
|
|
(
|
|
local children = #()
|
|
if undefined!=linkType_ShadowMesh then
|
|
RsSceneLink.GetChildren linkType_ShadowMesh model &children
|
|
else
|
|
print "linkType_ShadowMesh is undefined"
|
|
if ( children.count > 0 and not isDeleted children[1])
|
|
then
|
|
return ( children[1] )
|
|
else
|
|
return ( undefined )
|
|
)
|
|
|
|
fn RsLodDrawable_IsSimulationModel model = return RsLodDrawable_HasRenderModel model
|
|
|
|
fn RsLodDrawable_GetLODGroupHead obj =
|
|
(
|
|
local groupHead = obj
|
|
|
|
if (groupHead != undefined) do
|
|
(
|
|
local localparent
|
|
local headNotFound = True
|
|
while headNotFound do
|
|
(
|
|
localparent = (RsLodDrawable_GetHigherDetailModel groupHead)
|
|
if undefined==localparent then
|
|
localparent = RsLodDrawable_GetShadowMeshCounterPart groupHead
|
|
|
|
if (localparent == undefined)
|
|
then
|
|
(headNotFound = False)
|
|
else
|
|
(groupHead = localparent)
|
|
)
|
|
)
|
|
|
|
groupHead
|
|
)
|
|
|
|
fn RsLodDrawable_SetClothUserProps lodroot hasCloth clothTypeGroup =
|
|
(
|
|
-- This is a render chain if we have a simulation chain attached OR ARE WITHOUT LINKS AT ALL
|
|
local groupHead = (RsLodDrawable_GetLODGroupHead lodroot)
|
|
local groupHeadIsCloth = RsCloth.IsCloth groupHead
|
|
local isRenderChain = RsLodDrawable_HasSimulationModel groupHead
|
|
local isSimChain = groupHeadIsCloth and RsLodDrawable_HasRenderModel groupHead
|
|
-- mein cloth chain is either the simulation chain, or render chain if no simulation chain attached
|
|
local isMainClothChain = groupHeadIsCloth and not RsLodDrawable_HasSimulationModel groupHead and not isSimChain
|
|
local isFragmentRoot = (undefined==lodroot.parent)
|
|
|
|
-- print (lodroot.name+" with parent "+groupHead.name)
|
|
-- print ("isMainClothChain:"+isMainClothChain as string+"\nisRenderChain:"+isRenderChain as string+"\nisSimChain:"+isSimChain as string)
|
|
local exclusiveTypeGroups = #()
|
|
if isMainClothChain or isSimChain then
|
|
(
|
|
append exclusiveTypeGroups "ClothPiece"
|
|
if isMainClothChain then
|
|
(
|
|
if isFragmentRoot then
|
|
append exclusiveTypeGroups "fragments"
|
|
append exclusiveTypeGroups clothTypeGroup
|
|
)
|
|
setUserProp lodroot "specialFlags" clothTypeGroup
|
|
setuserprop lodroot "optimseMeshForCloth" true
|
|
setUserProp lodroot "optimize" false
|
|
)
|
|
else if isRenderchain then
|
|
(
|
|
if isFragmentRoot then
|
|
append exclusiveTypeGroups "fragments"
|
|
append exclusiveTypeGroups clothTypeGroup
|
|
setUserProp lodroot "specialFlags" clothTypeGroup
|
|
if RsVehicle!=true then -- can be undefined, so no boolean check
|
|
(
|
|
setuserprop lodroot "optimseMeshForCloth" true
|
|
)
|
|
setUserProp lodroot "optimize" false
|
|
)
|
|
else
|
|
(
|
|
exclusiveTypeGroups = #("fragments", "lodgroup")
|
|
RsUserProp_Clear lodroot "optimseMeshForCloth"
|
|
setUserProp lodroot "specialFlags" "lodgroup"
|
|
)
|
|
|
|
local groupString = RsStringArray exclusiveTypeGroups token:"|"
|
|
print (lodroot.name+":exclusiveTypeGroups:"+groupString )
|
|
setUserProp lodroot "exclusiveTypeGroups" groupString
|
|
)
|
|
|
|
fn RsLodDrawable_HasAnimatedParent obj = (
|
|
local isAnimated = false
|
|
if obj.parent != undefined and getattrclass obj.parent == "Gta Object" then (
|
|
local idxHasAnim = getattrindex "Gta Object" "Has Anim"
|
|
isAnimated = (getAttr obj.parent idxHasAnim)
|
|
|
|
)
|
|
isAnimated
|
|
)
|
|
|
|
--
|
|
-- name: RsLodDrawable_SetUserProps
|
|
-- desc: Setup max user properties for the complete Drawable LOD hierarchy
|
|
-- starting with the lodroot node specified.
|
|
-- return: Array of objects that have had lod user property set (typically
|
|
-- used for selection to then select nodes for Rex export).
|
|
--
|
|
-- This is recursive, when called from exporter enduser code DO NOT specify
|
|
-- the depth parameter unless you know what you are doing.
|
|
--
|
|
-- cloth parameters are for hierarchies that "have" cloth and object that "are" cloth.
|
|
-- clothTypeGroup is used to give hint on whether function is used to assemble meshes (and hence not setting some user attributes)
|
|
|
|
fn RsLodDrawable_SetUserProps lodroot &lodGroupCount \
|
|
depth:0 lastLodRange:0 lastLodDist:0 hasCloth:false isCloth:false clothTypeGroup:"lodgroup" doOptimize:true ignoreLeafReset:false =
|
|
(
|
|
local objs = #()
|
|
--format "RsLodDrawable_SetUserProps % %\n" lodroot depth
|
|
|
|
local idxIsCloth = getattrindex "Gta Object" "Is Cloth"
|
|
local lodDistAttrIndex = ( GetAttrIndex "Gta Object" "LOD distance" )
|
|
local lod_dist = ( GetAttr lodroot lodDistAttrIndex )
|
|
|
|
-- Set "lodthreshold" user property to LOD distance if we aren't
|
|
-- the lower detail model (fade distance will be used for that).
|
|
-- overridden throughout simulation chain descending
|
|
if not isCloth then
|
|
isCloth = getAttr lodroot idxIsCloth
|
|
|
|
if hasCloth then
|
|
(
|
|
lastLodDist = (lastLodDist + (lastLodRange/5))
|
|
setuserprop lodroot "lodthreshold" lastLodDist
|
|
setuserprop lodroot "lodoutthreshold" lod_dist
|
|
gRsUlog.LogMessage (lodroot.name+" lod in:"+lastLodDist as string+", out:"+lod_dist as string) context:lodroot
|
|
RsUserProp_Clear lodroot "optimize"
|
|
|
|
if undefined!=clothTypeGroup then
|
|
RsLodDrawable_SetClothUserProps lodroot hasCloth clothTypeGroup
|
|
)
|
|
else
|
|
(
|
|
if ( RsLodDrawable_HasLowerDetailModel lodroot ) then
|
|
(
|
|
setuserprop lodroot "lodthreshold" lastLodDist
|
|
setuserprop lodroot "lodoutthreshold" lod_dist
|
|
)
|
|
else
|
|
(
|
|
-- Ensure we don't have a "lodthreshold" property set.
|
|
RsUserProp_Clear lodroot "lodthreshold"
|
|
RsUserProp_Clear lodroot "lodoutthreshold"
|
|
)
|
|
RsUserProp_Clear lodroot "exclusiveTypeGroups"
|
|
RsUserProp_Clear lodroot "specialFlags"
|
|
)
|
|
|
|
if lastLodDist >= lod_dist then
|
|
(
|
|
gRsUlog.LogError ("Drawable LOD setup failed as LOD level object "+lodroot as string+" must have higher LOD distance set than its higher part \n("+lastLodDist as string+" >= "+lod_dist as string+").") context:lodroot
|
|
)
|
|
|
|
-- setting the lodgroup
|
|
if undefined!=clothTypeGroup then
|
|
(
|
|
setuserprop lodroot "lodgroup" lodGroupCount
|
|
gRsUlog.LogDebug ("Setting lodgroup of "+lodroot.name+" to "+lodGroupCount as string)
|
|
)
|
|
|
|
-- Set "lod" user property to our current depth (unless 0).
|
|
setuserprop lodroot "lod" depth
|
|
gRsUlog.LogDebug ("Set \"lod\" of " +lodroot.name + " to " + depth as string)
|
|
|
|
local anyChildren = #()
|
|
RsSceneLink.GetChildren -1 lodroot &anyChildren
|
|
local childCount = anyChildren.count
|
|
-- We bail out if the root object specified is not within
|
|
-- a drawable LOD hierarchy or if the object is animated.
|
|
if(not ( RsLodDrawable_HasLowerDetailModel lodroot ) and
|
|
not ( RsLodDrawable_HasSimulationModel lodroot ) and
|
|
( childCount==0 ) and
|
|
not ( RsLodDrawable_HasProxyModel lodroot) and
|
|
not ( RsLodDrawable_HasAnimatedParent lodroot ) ) then
|
|
(
|
|
-- Force LOD to 0, in case it was previously in a drawable
|
|
-- LOD hierarchy and no longer is.
|
|
if not ignoreLeafReset then
|
|
(
|
|
RsUserProp_Clear lodroot "lod"
|
|
RsUserProp_Clear lodroot "lodgroup"
|
|
)
|
|
return ( #() )
|
|
)
|
|
|
|
appendIfUnique objs lodroot
|
|
|
|
local parobj = ( RsSceneLink.GetParent linkType_DRAWLOD lodroot )
|
|
if ( undefined != parobj ) then
|
|
(
|
|
if (RsLodDrawable_HasSimulationModel lodroot) then
|
|
(
|
|
gRsUlog.LogError (lodroot.name + " has a LOD link is currently not supported. Please revise!") context:lodroot
|
|
)
|
|
else
|
|
(
|
|
subobjs = RsLodDrawable_SetUserProps parobj &lodGroupCount depth:(depth+1) lastLodRange:(lod_dist-lastLodDist) lastLodDist:lod_dist hasCloth:hasCloth isCloth:isCloth doOptimize:doOptimize clothTypeGroup:clothTypeGroup
|
|
join objs subobjs
|
|
)
|
|
)
|
|
|
|
local channelsToCheck = #(linkType_ShadowMesh)
|
|
for ch in channelsToCheck do
|
|
(
|
|
local parobj = ( RsSceneLink.GetParent ch lodroot )
|
|
if ( undefined != parobj ) then
|
|
(
|
|
subobjs = RsLodDrawable_SetUserProps parobj &lodGroupCount depth:(depth) lastLodRange:0 lastLodDist:0 hasCloth:hasCloth doOptimize:false clothTypeGroup:clothTypeGroup
|
|
join objs subobjs
|
|
)
|
|
)
|
|
|
|
local renderobj = ( RsLodDrawable_GetRenderModel lodroot )
|
|
-- print ("renderobj:"+renderobj as string)
|
|
if ( undefined != renderobj ) then
|
|
(
|
|
-- increment to add renderable chain to different group
|
|
lodGroupCount = lodGroupCount+1
|
|
-- set optimize to false!!
|
|
subobjs = RsLodDrawable_SetUserProps renderobj &lodGroupCount depth:(depth) lastLodRange:0 lastLodDist:0 hasCloth:hasCloth doOptimize:false clothTypeGroup:clothTypeGroup
|
|
join objs subobjs
|
|
)
|
|
|
|
local idxIsFragment = getattrindex "Gta Object" "Is Fragment"
|
|
local idxIsDynamic = getattrindex "Gta Object" "Is Dynamic"
|
|
if getattr lodroot idxIsCloth then
|
|
(
|
|
setattr lodroot idxIsDynamic true
|
|
setattr lodroot idxIsFragment true
|
|
)
|
|
|
|
objs = MakeUniqueArray objs
|
|
return objs
|
|
)
|
|
|
|
fn RsLodDrawable_GetAllModels lodroot =
|
|
(
|
|
local objs = #(lodroot)
|
|
|
|
local parobj = ( RsSceneLink.GetParent linkType_DRAWLOD lodroot )
|
|
if ( undefined != parobj ) then
|
|
(
|
|
subobjs = RsLodDrawable_GetAllModels parobj
|
|
join objs subobjs
|
|
)
|
|
|
|
local channelsToCheck = #(linkType_ShadowMesh)
|
|
for ch in channelsToCheck do
|
|
(
|
|
local parobj = ( RsSceneLink.GetParent ch lodroot )
|
|
if ( undefined != parobj ) then
|
|
(
|
|
subobjs = RsLodDrawable_GetAllModels parobj
|
|
join objs subobjs
|
|
)
|
|
)
|
|
|
|
local renderobj = ( RsLodDrawable_GetRenderModel lodroot )
|
|
-- print ("renderobj:"+renderobj as string)
|
|
if ( undefined != renderobj ) then
|
|
(
|
|
subobjs = RsLodDrawable_GetAllModels renderobj
|
|
join objs subobjs
|
|
)
|
|
|
|
objs = MakeUniqueArray objs
|
|
return objs
|
|
)
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- util functions
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
fn setupSliderAndHandler rc index caption target =
|
|
(
|
|
local lodidx = getAttrindex "Gta Object" "LOD distance"
|
|
if "Gta Object"!=(getattrclass target) then return false
|
|
rc.addControl #spinner ("control_"+index as string) caption paramStr:(" range:[0,10000,"+(getattr target lodidx) as string+"]")
|
|
rc.addHandler ("control_"+index as string) #changed paramStr:"val " codeStr:("if @Gta Object@==(getattrclass $"+target.name+") then setattr $"+target.name+" "+lodidx as string+" val") filter:true
|
|
)
|
|
|
|
fn RsLodDrawable_CreateLODSetupDialog =
|
|
(
|
|
local parentOfChain = RsLodDrawable_GetLODGroupHead selection[1]
|
|
if undefined==parentOfChain then
|
|
(
|
|
messagebox "select at least one object"
|
|
return false
|
|
)
|
|
local renderGrouplink = RsLodDrawable_GetSimulationModel parentOfChain
|
|
if undefined!=renderGrouplink then parentOfChain = renderGrouplink
|
|
local parentOfRenderChain = undefined
|
|
local localChainObjs = #()
|
|
-- find parent
|
|
RsLodDrawable_GetLODGroupHead parentOfChain
|
|
-- find render chain
|
|
local bottomOfChain = parentOfChain
|
|
while undefined!=bottomOfChain do
|
|
(
|
|
renderChild = (RsLodDrawable_GetSimulationModel bottomOfChain)
|
|
if undefined==renderChild then renderChild = (RsLodDrawable_GetRenderModel bottomOfChain)
|
|
if undefined!=renderChild then
|
|
(
|
|
parentOfRenderChain = renderChild
|
|
exit
|
|
)
|
|
bottomOfChain = (RsLodDrawable_GetLowerDetailModel bottomOfChain)
|
|
)
|
|
--find parent of render chain
|
|
RsLodDrawable_GetLODGroupHead parentOfRenderChain
|
|
|
|
local rc = RolloutCreator "RsLodHierSetup" "Setup LOD hierarchy"
|
|
rc.begin()
|
|
-- find render chain
|
|
bottomOfChain = parentOfChain
|
|
local controlindex = 0
|
|
--rc.addtext "group @current group@ (" filter:true
|
|
rc.addControl #label "groupLabel1" "current group:"
|
|
while undefined!=bottomOfChain do
|
|
(
|
|
setupSliderAndHandler rc controlindex (bottomOfChain.name+" distance") bottomOfChain
|
|
bottomOfChain = (RsLodDrawable_GetLowerDetailModel bottomOfChain)
|
|
controlindex = controlindex+1
|
|
)
|
|
-- rc.addtext ")"
|
|
if undefined!=parentOfRenderChain then
|
|
(
|
|
-- rc.addtext "group @attached group@ (" filter:true
|
|
rc.addControl #label "groupLabel2" "attached group:"
|
|
local bottomOfRenderChain = parentOfRenderChain
|
|
-- local controlindex = 0
|
|
while undefined!=bottomOfRenderChain do
|
|
(
|
|
setupSliderAndHandler rc controlindex (bottomOfRenderChain.name+" distance") bottomOfRenderChain
|
|
bottomOfRenderChain = (RsLodDrawable_GetLowerDetailModel bottomOfRenderChain)
|
|
controlindex = controlindex+1
|
|
)
|
|
-- rc.addtext ")"
|
|
)
|
|
CreateDialog (rc.end()) 300 300 modal:true
|
|
)
|
|
|
|
|
|
-- drawablelod.ms
|