422 lines
10 KiB
Plaintext
Executable File
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]
|
|
) |