Files
2025-09-29 00:52:08 +02:00

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