Files
gtav-src/tools_ng/dcc/current/max2012/scripts/pipeline/util/scene.ms
T
2025-09-29 00:52:08 +02:00

422 lines
10 KiB
Plaintext
Executable File

-- file: scene.ms
-- file with helpers for scene objects
-- author; GunnarD
filein "pipeline/ui/GuidComparison_ui.ms"
fn RsMouseclickBoundsIntersect viewPoint:mouse.screenpos =
(
local theObjs = objects as array
-- local viewPoint = mouse.screenpos
-- if undefined!=worldRay then
-- viewPoint =
local foundObjs = #()
for o in theObjs do in coordsys screen
(
if o.isHiddenInVpt then o.isHidden = true
local colour = random (color 0 0 0) (color 255 255 255)
local thecoodsys = (inverse (getViewTM()))
local bb = nodeGetBoundingBox o thecoodsys
local viewSpacePoint = mapScreenToView viewPoint (bb[1].z+((bb[2].z-bb[1].z)/2))
-- in coordsys thecoodsys point pos:bb[1] color:colour
-- in coordsys thecoodsys point pos:bb[2] color:colour
-- print o
-- print bb[1]
-- print bb[2]
-- print viewSpacePoint
-- print "++++"
if viewSpacePoint.x < bb[2].x and
viewSpacePoint.y < bb[2].y and
viewSpacePoint.x > bb[1].x and
viewSpacePoint.y > bb[1].y then
(
local depthindex = foundObjs.count
while depthindex>1 and foundObjs[depthindex].pos.z < o.pos.z do
(
depthindex = depthindex-1
)
if depthindex<=0 then depthindex =1
insertItem o foundObjs depthindex
)
)
-- print foundObjs
return foundObjs
)
fn RsMousePosGridIntersect =
(
-- http://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm:
-- Ray: P = P0 + tV
-- Plane: P . N + d = 0
-- subst for P:
-- (P0 + tV) . N + d = 0
-- t = -(P0 . N + d) / (V . N)
-- P(intersection) = P0 + tV
local mouseRay = mapScreenToWorldRay mouse.pos
local N = [0,0,1]
local d = 0
local P0 = mouseRay.pos
local V = mouseRay.dir
local t = -(dot P0 N) / (dot V N)
local gridPoint = P0 + (V * t)
return gridPoint
)
-- nicked from http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
--
-- bool SpherePrimitive::intersect(const Ray& ray, float* t)
-- {
-- //Compute A, B and C coefficients
-- float a = dot(ray.d, ray.d);
-- float b = 2 * dot(ray.d, ray.o);
-- float c = dot(ray.o, ray.o) - (r * r);
-- //Find discriminant
-- float disc = b * b - 4 * a * c;
--
-- // if discriminant is negative there are no real roots, so return
-- // false as ray misses sphere
-- if (disc < 0)
-- return false;
-- // compute q as described above
-- float distSqrt = sqrtf(disc);
-- float q;
-- if (b < 0)
-- q = (-b - distSqrt)/2.0;
-- else
-- q = (-b + distSqrt)/2.0;
-- // compute t0 and t1
-- float t0 = q / a;
-- float t1 = c / q;
-- // make sure t0 is smaller than t1
-- if (t0 > t1)
-- {
-- // if t0 is bigger than t1 swap them around
-- float temp = t0;
-- t0 = t1;
-- t1 = temp;
-- }
-- // if t1 is less than zero, the object is in the ray's negative direction
-- // and consequently the ray misses the sphere
-- if (t1 < 0)
-- return false;
-- // if t0 is less than zero, the intersection point is at t1
-- if (t0 < 0)
-- {
-- t = t1;
-- return true;
-- }
-- // else the intersection point is at t0
-- else
-- {
-- t = t0;
-- return true;
-- }
-- }
fn RsSphereRayIntersect sphereRadius theRay clipToRadius:true =
(
--Compute A, B and C coefficients
local a = (dot theRay.dir theRay.dir);
local b = 2 * (dot theRay.dir theRay.pos);
local c = (dot theRay.pos theRay.pos) - (sphereRadius * sphereRadius);
--Find discriminant
local disc = b * b - 4 * a * c;
-- if discriminant is negative there are no real roots, so return
-- false as ray misses sphere
if (disc < 0) then
(
if clipToRadius then
disc = 0
else
return undefined
)
-- compute q as described above
local distSqrt = (sqrt disc)
local q
if (b < 0) then
q = (-b - distSqrt)/2.0;
else
q = (-b + distSqrt)/2.0;
-- compute t0 and t1
local t0 = q / a;
local t1 = c / q;
-- make sure t0 is smaller than t1
if (t0 > t1) then
(
-- if t0 is bigger than t1 swap them around
local temp = t0;
t0 = t1;
t1 = temp;
)
-- if t1 is less than zero, the object is in the ray's negative direction
-- and consequently the ray misses the sphere
if (t1 < 0) then
return undefined;
-- if t0 is less than zero, the intersection point is at t1
if (t0 < 0) then
(
return theRay.pos + (theRay.dir * t1)
)
-- else the intersection point is at t0
else
(
return theRay.pos + (theRay.dir * t0)
)
)
-- CheckSceneForLightIDProbs
--
-- Description: Used for lights to find unique attribute Guids
fn RecCheckGuid root usedIds objectPairs =
(
local objGuid = getattrguid root
if usedIds.containsKey objGuid then
(
if (getNodeByName root.name all:true).count>1 then
gRsUlog.LogError ("Name "+root.name+" found on more than one object!") context:root.name
else if (root.name!=(usedIds.item objGuid)) then
(
append objectPairs (DataPair root.name (usedIds.item objGuid))
gRsUlog.LogError ("Object's "+root.name+" global ID is already used. Please \"Rs Utils -> Rs Organisational -> GUID Tools -> Reset Object GUID\". https://devstar.rockstargames.com/wiki/index.php/Map_Export_Errors#Duplicate_Attribute_GUID") context:root
)
)
else
usedIds.add objGuid root.name
for c in root.children where "Gta Object"==(getattrclass c) and not isrsref c do
(
RecCheckGuid c usedIds objectPairs
)
)
fn CheckSceneForLightIDProbs feedback:false map: showComparisonDialog:false =
(
local objs
if (map != unsupplied) then
(
if (map.name != undefined) do
(
local contentNode = RsContentTree.GetContentNode map.filename
if ( contentNode == undefined ) then
(
gRsUlog.LogError ("No map node found for " + map.filename)
return false
)
if RsContentTree.GetMapType( contentNode ) != "props" then
(
gRsUlog.LogMessage ("non prop map "+map.name+". No light check needed.")
return true
)
)
objs = map.objects
)
else
(
objs = objects
)
local usedIds = dotnetobject "RSG.MaxUtils.MaxDictionary"
local objpairs = #()
pushPrompt "Checking object GUIDs..."
for o in objs where "Gta Object"==(getattrclass o) and not isrsref o do
(
RecCheckGuid o usedIds objpairs
)
popPrompt()
if not showComparisonDialog then
(
return gRsUlog.Validate()
)
else if objpairs.count>0 then
(
CreateGuidCompareDialog objpairs
return false
)
if feedback then
messagebox "No problems found in scene.\nThis is only a local scene check though and other problems might occur globally if guid is reused."
return true
)
fn RsGenericRec root func =
(
func root
for c in root.children do
RsGenericRec c func
)
fn RsCollectChildren root kids =
(
appendIfUnique kids root
for c in root.children do
RsCollectChildren c kids
)
fn HasVisTrack obj = (undefined != (getVisController obj))
fn RsHasVisTrackRec obj =
(
if HasVisTrack obj then
return true
for c in obj.children do
if RsHasVisTrackRec c then
return true
return false
)
--------------------------------------------------------------
-- Find out if this node is supposed to be exported
--------------------------------------------------------------
fn IsExportRootNode obj =
(
local childLinks = RsSceneLink.GetNodeChildLinkTypes obj
local parentLinks= RsSceneLink.GetNodeParentLinkTypes obj
return (getattrclass obj == "Gta Object") and
0 == findItem childLinks LinkType_DRAWLOD and
0 == findItem childLinks LinkType_ShadowMesh
)
fn GetExportRootNode obj =
(
if undefined==obj then
return undefined
-- foudn one!!
if IsExportRootNode obj and IsExportRootParent obj.parent then
return obj
-- checking max hierarchy
local foundNode = GetExportRootNode obj.parent
if undefined!=foundNode then
return foundNode
local linkChildren = #()
-- checking custom link hierarchy
RsSceneLink.GetChildren LinkType_DRAWLOD obj &linkChildren
RsSceneLink.GetChildren LinkType_ShadowMesh obj &linkChildren
for child in linkChildren do
(
local foundNode = GetExportRootNode child
if undefined!=foundNode then
return foundNode
)
--nae luck
return undefined
)
-- Find out whether this is an object that serves as a root to link drawables to.
fn IsExportRootParent obj =
(
(undefined == obj) or
(rootnode == obj) or
(undefined!=Containers.IsContainerNode obj) or
(classof obj==GtaMloRoom)
)
fn GetContainer obj =
(
if IsExportRootParent obj then
obj
else if undefined!=obj.parent then
(GetContainer obj.parent)
else
undefined
)
fn RsLinkDepth obj =
(
local lodDepthCheck = obj
local depth = 0
local children = #()
RsSceneLink.GetChildren LinkType_LOD lodDepthCheck &children
lodDepthCheck = children[1]
while (lodDepthCheck!=undefined) do
(
local children = #()
RsSceneLink.GetChildren LinkType_LOD lodDepthCheck &children
lodDepthCheck = children[1]
depth += 1
)
return depth
)
fn GetRootNodes nodes =
(
local roots = #()
for n in nodes do
(
local parent = n
while undefined!=parent and not IsExportRootParent parent.parent do
(
parent = parent.parent
)
appendIfUnique roots parent
)
roots
)
fn CheckForCirclularDependeciesRec root parents:#() =
(
for p in parents where 0!=(finditem (refs.dependents root) p) do
(
local err = stringstream ""
format "Circular dependency: % dependent on % while the latter being a child of the former." p root to:err
gRsUlog.LogError err context:#(p,root)
)
newParents = copy parents #noMap
append newParents root
for c in root.children do
CheckForCirclularDependeciesRec c parents:newParents
)
fn CheckForCirclularDependecies =
(
for o in rootNode.children do CheckForCirclularDependeciesRec o
)
fn GetClothChildren root clothChildren:#() =
(
if RsCloth.IsCloth root then
appendIfUnique clothChildren root
for child in root.children do
GetClothChildren child clothChildren:clothChildren
)
-- Gets the first dependent of a specified class
fn RsGetDependent obj class =
(
(for Dependant in Refs.Dependents obj where (isValidNode Dependant and ClassOf Dependant == class) collect Dependant)[1]
)