446 lines
13 KiB
Plaintext
Executable File
446 lines
13 KiB
Plaintext
Executable File
--try (destroyDialog RsLodViewToolRoll) catch ()
|
|
|
|
rollout RsLodViewToolRoll "LOD Visualisation"
|
|
(
|
|
local lodViewObj
|
|
local toolIsOpen = false
|
|
|
|
checkButton btnVisActive "LOD Visualisation" offset:[-12,4] across:2
|
|
checkBox chkLodSpheres "Show as spheres" offset:[-14,-2]
|
|
checkBox chkShowSourceLods "Show source-obj distances" pos:(chkLodSpheres.pos + [0, 20])
|
|
radioButtons rdoShowSelAll "Show for:" labels:#("Sel. Objs", "Sel. Hierarchy", "All Objs") offset:[0,-6]
|
|
|
|
-- Used to define the lod-render bits:
|
|
struct renderItem (clr, class = #line, points = #(), extra)
|
|
local renderList = #()
|
|
|
|
fn renderLodView =
|
|
(
|
|
-- Only continue drawing if editor-tool is still open:
|
|
if not toolIsOpen do
|
|
(
|
|
unregisterRedrawViewsCallback renderLodView
|
|
return OK
|
|
)
|
|
|
|
gw.setTransform (Matrix3 1)
|
|
|
|
local lineClr, textClr
|
|
for item in renderList do
|
|
(
|
|
local points = for pos in item.points collect (gw.wtransPoint pos)
|
|
|
|
case item.class of
|
|
(
|
|
#line:
|
|
(
|
|
gw.setColor #line item.clr
|
|
gw.wPolyline points item.extra
|
|
)
|
|
#marker:
|
|
(
|
|
gw.Marker points[1] item.extra color:item.clr
|
|
)
|
|
#text:
|
|
(
|
|
gw.setColor #text item.clr
|
|
gw.text points[1] item.extra
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Returns position of point val (0->1) along bezier defined by three points:
|
|
fn quadraticBezierPoint posA posB posC val =
|
|
(
|
|
local t = 1 - val
|
|
local sn = 1 - t
|
|
local retVal = [0,0,0]
|
|
retVal.X = posA.x*t*t + posB.x*2*t*Sn + posC.x*sn*sn;
|
|
retVal.Y = posA.y*t*t + posB.y*2*t*Sn + posC.y*sn*sn;
|
|
retVal.Z = posA.z*t*t + posB.z*2*t*Sn + posC.z*sn*sn;
|
|
|
|
return retVal
|
|
)
|
|
|
|
fn getArcPoints startPoint endPoint height arrow:true =
|
|
(
|
|
local points = #()
|
|
|
|
local lineVec = endPoint - startPoint
|
|
local midPoint = startPoint + (0.5 * lineVec)
|
|
|
|
local startPoint2d = [startPoint.x, startPoint.y]
|
|
local endPoint2d = [endPoint.x, endPoint.y]
|
|
local dist2d = distance startPoint2d endPoint2d
|
|
|
|
local absHeight = abs height
|
|
if (dist2d < absHeight) do
|
|
(
|
|
height *= (dist2d / absHeight)
|
|
)
|
|
midPoint += [0, 0, height]
|
|
|
|
local arrowSize = 3.0
|
|
|
|
-- Don't arc line if nearly vertical:
|
|
local stepper = if (abs height > 0.1) then (1.0 / 6) else 1.0
|
|
|
|
local points = for val = 0.0 to 1.0 by stepper collect
|
|
(
|
|
quadraticBezierPoint startPoint midPoint endPoint val
|
|
)
|
|
|
|
if arrow do
|
|
(
|
|
local arrowStartVal = 1.0 - (arrowSize / (distance startPoint endPoint))
|
|
local arrowStartPos = quadraticBezierPoint startPoint midPoint endPoint arrowStartVal
|
|
local arrowVec = (endPoint - arrowStartPos)
|
|
local arrowParaVec = arrowSize * (normalize (cross arrowVec (arrowVec + [0,0,1])))
|
|
|
|
append points (arrowStartPos + arrowParaVec)
|
|
append points (arrowStartPos - arrowParaVec)
|
|
append points endPoint
|
|
)
|
|
|
|
return points
|
|
)
|
|
|
|
fn getCirclePoints pos radius segs =
|
|
(
|
|
local slice = 360.0 / segs
|
|
|
|
for n = 0 to (segs - 1) collect
|
|
(
|
|
local ang = slice * n
|
|
[pos.x + (radius * (cos ang)), pos.y + (radius * (sin ang)), pos.z]
|
|
)
|
|
)
|
|
|
|
local showObjItems = #()
|
|
|
|
-- Update render-data:
|
|
fn updateLodView updateObjList:true doRedraw:true =
|
|
(
|
|
-- Clear the current render-list:
|
|
renderList.count = 0
|
|
|
|
if not btnVisActive.checked do
|
|
(
|
|
deleteAllChangeHandlers id:#RsLodViewTool
|
|
return OK
|
|
)
|
|
|
|
unregisterRedrawViewsCallback renderLodView
|
|
|
|
-- Get render-options from UI:
|
|
local showAll = (rdoShowSelAll.state == 3)
|
|
local showHierarchy = (rdoShowSelAll.state == 2)
|
|
local drawSpheres = chkLodSpheres.checked
|
|
local showSourceLods = chkShowSourceLods.checked
|
|
|
|
if updateObjList then
|
|
(
|
|
-- Get scene-objects per lod-level:
|
|
local lodLevelledObjs = RsGetLodLevelObjs()
|
|
|
|
showObjItems = #()
|
|
for lodLevel = 1 to lodLevelledObjs.count do
|
|
(
|
|
local objList = lodLevelledObjs[lodLevel]
|
|
join showObjItems (for obj in objList where (showAll or obj.isSelected) and (not obj.isHidden) collect (dataPair obj:obj lodLevel:lodLevel))
|
|
)
|
|
|
|
-- Add selected-object parents/child hierarchies to to-render list:
|
|
if showHierarchy do
|
|
(
|
|
local parentObjItems = deepCopy showObjItems
|
|
local objNum = 0
|
|
while (objNum < parentObjItems.count) do
|
|
(
|
|
objNum += 1
|
|
|
|
local objItem = parentObjItems[objNum]
|
|
local objPar = RsSceneLink.getparent LinkType_LOD objItem.obj
|
|
if (objPar != undefined) do
|
|
(
|
|
append parentObjItems (dataPair obj:objPar lodLevel:(objItem.lodLevel + 1))
|
|
)
|
|
)
|
|
parentObjItems = for n = (showObjItems.count + 1) to parentObjItems.count collect parentObjItems[n]
|
|
|
|
local childObjItems = deepCopy showObjItems
|
|
local objNum = 0
|
|
while (objNum < childObjItems.count) do
|
|
(
|
|
objNum += 1
|
|
|
|
local objItem = childObjItems[objNum]
|
|
local childLodLevel = objItem.lodLevel - 1
|
|
|
|
local objChildItems = for childObj in (RsGetLODChildren objItem.obj) collect (dataPair obj:childObj lodLevel:childLodLevel)
|
|
|
|
join childObjItems objChildItems
|
|
)
|
|
childObjItems = for n = (showObjItems.count + 1) to childObjItems.count collect childObjItems[n]
|
|
|
|
-- Add unique-object items to main list:
|
|
local objsList = for item in showObjItems collect item.obj
|
|
for item in parentObjItems do
|
|
(
|
|
if (not item.obj.isHidden) and (appendIfUnique objsList item.obj) do (append showObjItems item)
|
|
)
|
|
for item in childObjItems do
|
|
(
|
|
if (not item.obj.isHidden) and (appendIfUnique objsList item.obj) do (append showObjItems item)
|
|
)
|
|
)
|
|
|
|
-- Set up change-handers for our objects:
|
|
local objs = for item in showObjItems collect item.obj
|
|
|
|
deleteAllChangeHandlers id:#RsLodViewTool
|
|
when objs deleted id:#RsLodViewTool do (updateLodView updateObjList:false doRedraw:false)
|
|
when transform objs changes id:#RsLodViewTool do (updateLodView updateObjList:false doRedraw:false)
|
|
when parameters objs changes id:#RsLodViewTool do (updateLodView updateObjList:false doRedraw:false)
|
|
)
|
|
|
|
-- Collect refDefs first, to preload lod-distances if required.
|
|
-- (Using refNums bitarray to avoid doing isRsRef check multiple times)
|
|
local refNums = #{}
|
|
local contRefNums = #{}
|
|
|
|
refNums.count = showObjItems.count
|
|
contRefNums.count = showObjItems.count
|
|
|
|
local refDefs = for objNum = 1 to showObjItems.count collect
|
|
(
|
|
local obj = showObjItems[objNum].obj
|
|
case of
|
|
(
|
|
(isRsRef obj):
|
|
(
|
|
refNums[objNum] = true
|
|
obj.refDef
|
|
)
|
|
(RsIsContainerLod obj):
|
|
(
|
|
contRefNums[objNum] = true
|
|
obj.refDef
|
|
)
|
|
default:dontCollect
|
|
)
|
|
)
|
|
refDefs = makeUniqueArray refDefs
|
|
RsRefFuncs.loadLodDistances refDefs
|
|
|
|
struct lodObjStruct (obj, isRef = false, isContRef = false, refdef, instLod = false, lodDist, sourceLodDist, lodParent, lodLevel)
|
|
|
|
local objItems = for objNum = 1 to showObjItems.count collect
|
|
(
|
|
local objItem = showObjItems[objNum]
|
|
local obj = objItem.obj
|
|
|
|
local listItem = lodObjStruct obj:obj isRef:refNums[objNum] isContRef:contRefNums[objNum] lodLevel:objItem.lodLevel
|
|
|
|
local instLod = true
|
|
local refDef
|
|
|
|
case of
|
|
(
|
|
(listItem.isRef):
|
|
(
|
|
refDef = listItem.refDef = obj.refDef
|
|
instLod = getAttr obj idxInstLodDistance
|
|
)
|
|
(listItem.isContRef):
|
|
(
|
|
refDef = listItem.refDef = obj.refDef
|
|
instLod = false
|
|
)
|
|
)
|
|
|
|
listItem.instLod = instLod
|
|
|
|
listItem.lodDist = if instLod then
|
|
(
|
|
listItem.sourceLodDist = if (refDef == undefined) then undefined else
|
|
(
|
|
refDef.lodDistance
|
|
)
|
|
|
|
getAttr obj idxLodDistance
|
|
)
|
|
else
|
|
(
|
|
if (refDef == undefined) then undefined else
|
|
(
|
|
refDef.lodDistance
|
|
)
|
|
)
|
|
|
|
if (listItem.lodDist != undefined) then listItem else dontCollect
|
|
)
|
|
|
|
-- Paramblock list causes updates whenever these objects are changed:
|
|
drawNodes = for item in objItems collect item.obj
|
|
|
|
local instLodClr = (color 180 255 180)
|
|
local refLodClr = Black
|
|
|
|
-- Avoid adding similar circles more than once:
|
|
local addedCircleHashes = #()
|
|
|
|
for item in objItems do
|
|
(
|
|
local drawColour = if item.instLod then instLodClr else refLodClr
|
|
|
|
local obj = item.obj
|
|
local objPos = obj.pos
|
|
local lodDist = item.lodDist
|
|
local sourceLodDist = item.sourceLodDist
|
|
|
|
local lodParent = item.lodParent = RsSceneLink.getparent LinkType_LOD obj
|
|
local hasParent = (lodParent != undefined)
|
|
local lodPivot = if hasParent then lodParent.pos else obj.pos
|
|
|
|
local backXform, rotXformA, rotXformB
|
|
if drawSpheres do
|
|
(
|
|
backXform = transMatrix -lodPivot
|
|
|
|
rotXformA = rotateXMatrix 90
|
|
rotXformA[4] = lodPivot
|
|
|
|
rotXformB = rotateZMatrix 90
|
|
rotXformB[4] = lodPivot
|
|
)
|
|
|
|
-- Add main LOD circles:
|
|
local thisLodDist = lodDist
|
|
local thisClr = drawColour
|
|
local hasLevels = (item.lodLevel != 1)
|
|
|
|
-- Draw non-selected objects with slightly darker circles:
|
|
if (not obj.isSelected) do (thisClr *= 0.7)
|
|
|
|
local circleHash = getHashValue #(thisClr, lodPivot, thisLodDist, item.lodLevel, 0) 1
|
|
|
|
if (appendIfUnique addedCircleHashes circleHash) do
|
|
(
|
|
for levelNum = 1 to item.lodLevel do
|
|
(
|
|
local circlePoints = getCirclePoints [0,0,0] thisLodDist 28
|
|
append renderList (renderItem clr:thisClr class:#line points:(for pos in circlePoints collect (pos + lodPivot)) extra:true)
|
|
|
|
-- Only draw extra lod-level circles for main circle, not for sphere-circles:
|
|
if drawSpheres and (levelNum == 1) do
|
|
(
|
|
append renderList (renderItem clr:thisClr class:#line points:(for pos in circlePoints collect (pos * rotXformA)) extra:true)
|
|
append renderList (renderItem clr:thisClr class:#line points:(for pos in circlePoints collect (pos * rotXformB)) extra:true)
|
|
)
|
|
|
|
-- Draw extra lines per lod-level - 10m spacing, darker as they go out
|
|
if hasLevels do
|
|
(
|
|
thisLodDist += 5.0
|
|
thisClr *= 0.7
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Add dashed circle for prop's source-object lod-distance:
|
|
if showSourceLods and (sourceLodDist != undefined) do
|
|
(
|
|
local circleHash = getHashValue #(refLodClr, lodPivot, sourceLodDist, 1, 1) 1
|
|
|
|
if (appendIfUnique addedCircleHashes circleHash) do
|
|
(
|
|
local circlePoints = getCirclePoints [0,0,0] sourceLodDist 40
|
|
append circlePoints circlePoints[1]
|
|
|
|
local circleDashes = for n = 1 to (circlePoints.count - 1) by 2 collect #(circlePoints[n] + lodPivot, circlePoints[n + 1] + lodPivot)
|
|
|
|
if drawSpheres do
|
|
(
|
|
join circleDashes (for n = 1 to (circlePoints.count - 1) by 2 collect #(circlePoints[n] * rotXformA, circlePoints[n + 1] * rotXformA))
|
|
join circleDashes (for n = 1 to (circlePoints.count - 1) by 2 collect #(circlePoints[n] * rotXformB, circlePoints[n + 1] * rotXformB))
|
|
)
|
|
|
|
join renderList (for item in circleDashes collect (renderItem clr:refLodClr class:#line points:item extra:false))
|
|
)
|
|
)
|
|
|
|
-- Add arc to parent, if pivots are different:
|
|
if hasParent and ((distance objPos lodPivot) > 0.1) do
|
|
(
|
|
local arcClr = drawColour * 0.7
|
|
local arcPoints = getArcPoints objPos lodPivot (-0.15 * lodDist)
|
|
append renderList (renderItem clr:arcClr class:#line points:arcPoints extra:false)
|
|
|
|
append renderList (renderItem clr:drawColour class:#marker points:#(objPos) extra:#xMarker)
|
|
)
|
|
|
|
-- Add lod-pivot marker:
|
|
append renderList (renderItem clr:drawColour class:#marker points:#(lodPivot) extra:#circle)
|
|
)
|
|
|
|
registerRedrawViewsCallback renderLodView
|
|
|
|
if doRedraw do
|
|
(
|
|
completeRedraw()
|
|
)
|
|
|
|
return OK
|
|
)
|
|
|
|
fn removeCallbacks =
|
|
(
|
|
renderList.count = 0
|
|
deleteAllChangeHandlers id:#RsLodViewTool
|
|
callbacks.removeScripts id:#RsLodViewTool
|
|
unregisterRedrawViewsCallback renderLodView
|
|
)
|
|
|
|
fn setupCallbacks =
|
|
(
|
|
callbacks.addScript #selectionSetChanged "RsLodViewToolRoll.updateLodView()" id:#RsLodViewTool
|
|
callbacks.addScript #filePostOpenProcess "RsLodViewToolRoll.updateLodView()" id:#RsLodViewTool
|
|
callbacks.addScript #filePostSaveProcess "RsLodViewToolRoll.updateLodView()" id:#RsLodViewTool
|
|
callbacks.addScript #systemPostReset "RsLodViewToolRoll.updateLodView()" id:#RsLodViewTool
|
|
callbacks.addScript #systemPostNew "RsLodViewToolRoll.updateLodView()" id:#RsLodViewTool
|
|
registerRedrawViewsCallback renderLodView
|
|
)
|
|
|
|
on btnVisActive changed state do
|
|
(
|
|
updateLodView()
|
|
if not state do (completeRedraw())
|
|
)
|
|
on chkLodSpheres changed state do (updateLodView updateObjList:false)
|
|
on chkShowSourceLods changed state do (updateLodView updateObjList:false)
|
|
on rdoShowSelAll changed state do (updateLodView())
|
|
|
|
on RsLodViewToolRoll open do
|
|
(
|
|
toolIsOpen = true
|
|
setupCallbacks()
|
|
updateLodView()
|
|
)
|
|
|
|
on RsLodViewToolRoll close do
|
|
(
|
|
toolIsOpen = false
|
|
removeCallbacks()
|
|
if btnVisActive.checked do (completeRedraw())
|
|
)
|
|
|
|
-- Save rolled-up state:
|
|
on RsLodViewToolRoll rolledUp down do
|
|
(
|
|
RsSettingWrite "RsLodViewToolRoll" "rollup" (not down)
|
|
)
|
|
)
|
|
|
|
--createDialog RsLodViewToolRoll width:300 |