-- Author:Raptor5 -- Name:GES_SplineToCoord -- Description: -- Icon: -- Hide: no -- Version: 1.5.0 -- PARAMETERS ------------------------------------------------------------------ local segmentSpacing = 1.0 --[float] minimum road segment spacing | >= 0.5 local xmlOutputPath = "C:/Users/lukas/Documents" --[string] output folder path for generated xml-file local snapToNearbyAnchor = true --[bool] snaps start and end to nearby spline-anchor *) local snapIndex = 1 --[(0,1)] snapindex used for spline-anchor local snapSearchRadius = 1.0 --[float] spherical searchradius for nearby anchors -- Terrain Adjustment & Object placement local terrainRes = 1 --[int] Resolution of Terrain (meter per Pixel) default = 2 local setTerrainHeight = true --[bool] set Terrain-height by Spline local heightAdjustWidth = 6.0 --[float] width of terrain height adjustment (streetwidth + ~2m) local paintTerrainTexture = true --[bool] enable/disable Layer Painting local terrainLayerId = 1 --[int] LayerId for Painted Layer (see Documentation) local paintWidth = 5.0 --[float] with of Layerpainting (~ streetwidth +1.0 local placeReflectors = false --[bool] place Reflectors near the Road *) & **) local reflGrpName = "leitpfosten_w_grp8m" --[string] Reflector Group Name local reflectorDistance = 25.0 --[float] distance between reflectors -- Foliage Adjustment -- DensityMaps see Documentation ! local pathFruitDensityGdm = "FS22_Schwaadeheim/maps/mapUS/data/densityMap_fruits.gdm" local pathGroundDensityGdm = "FS22_Schwaadeheim/maps/mapUS/data/densityMap_ground.gdm" local forceReload = false --[bool] force Reload Densitymaps See documentation default=false local roadWidth = 4.0 --[float] width od the road in meter local clearFoliage = true --[bool] delete all Foliage and TerrainDetail along spline with road width local drawSideFoliage = true --[bool] create Foliage on the RoadSides local sideFoliageWith = 0.5 --[float] with of sideFoliage on each side local sideFoliageName = "meadow" --[string] name of Foliage used on Sides local sideFoliageState = 2 --[int] layerstate of Sidefoliage (see documentation) --[[ ++++ IPORTANT README ++++ *) For Anchor Snapping and Reflector Placement ensure following TG-structure exists: |- Roads |- SplineScriptSource | |_ Reflectors & other Sources ... |- Crossings |_ Crossings containing Spline Anchors ... **) Use ReflectorPairs (single TG) inside Group named SplineScriptSource ]] -- [!]Code Section do NOT modify below [!] ---------------------- ------------------------------------------------------------------ -- includes source("GES_R5Utils.lua") source("GES_R5TerrainUtils.lua") source("GES_R5FoliageUtils.lua") -- VARIABLES ------------------------------------------------------------------ local spline = getSelection(0) -- get Selected Spline local posOutputXml = createXMLFile(getName(spline), xmlOutputPath..getName(spline)..".xml", "SplineCoords") -- xml-output local numCV = getSplineNumOfCV(spline) local sLength = getSplineLength(spline) local numSc = 0 local currentPos = 0.0 -- current position on spline local x, y, z -- world coords local rx, ry, rz -- world vectors --get Road TG local roadsystem = R5Utils.searchNodeByName(getChildAt(getRootNode(),0),"Roads") if roadsystem == 0 then print("ERROR: Transformgroup Roads not found!") return end local anchorList = snapToNearbyAnchor and R5Utils.searchAllNodesByName(roadsystem, "SplineAnchor"..snapIndex, false, false) or nil -- ERRORHANDLING ------------------------------------------------------------------ if segmentSpacing < 0.5 then print("ERROR: segmentSpacing must be greater or equal 0.5") return end if node == 0 then print("ERROR: Please select valid Spline!") return end if getIsSplineClosed(spline) then print("ERROR: Spline must be open!") return end if getSplineLength(spline) < 1 then print("ERROR: Spline Legnth must be greater or equal 1.0") return end -- FUNCTIONS ------------------------------------------------------------------ -- write coord and vector as xml node function addXmlNode(index, x, y, z, dx, dy, dz) --write endcoord to file setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#x", x) setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#y", y) setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#z", z) --write enddirections to file setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#dx", dx) setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#dy", dy) setXMLFloat(posOutputXml, "SplineCoords.Points.v("..index..")#dz", dz) end -- search nearby function getNearbyAnchorPos(x, y, z, list) local nearestNode = R5Utils.getNearestNode(x,y,z, list) local x1,y1,z1 = getWorldTranslation(nearestNode) return x1,y1,z1, nearestNode end -- adjust anchor directionvector function adjustAnchorVector(anchorId, spline, splinePos) local adx, ady, adz = R5Utils.nodeRotationToVector(anchorId) local sdx, sdy, sdz = getSplineDirection(spline, currentPos) local alignment = ((adx * sdx)+(ady * sdy)+(adz * sdz)) if alignment > 0 then -- direction ok return adx,ady,adz else -- invert anchor direction return -adx, -ady, -adz end end -- MAIN ------------------------------------------------------------------ print(">> SplineToCoord: exporting "..getName(spline)) setXMLString(posOutputXml, "SplineCoords.param#name", getName(spline)) setXMLFloat(posOutputXml, "SplineCoords.param#len", sLength) setXMLFloat(posOutputXml, "SplineCoords.param#segment", segmentSpacing) -- get Spline-center Coords for translation adjust local scX, scY, scZ = getSplinePosition(spline, 0.5) setXMLFloat(posOutputXml, "SplineCoords.center#x", scX) setXMLFloat(posOutputXml, "SplineCoords.center#y", scY) setXMLFloat(posOutputXml, "SplineCoords.center#z", scZ) --get coords from spline while currentPos < 1 do if snapToNearbyAnchor and currentPos == 0 then local a,b,c = getSplinePosition(spline, currentPos) x,y,z, anchorId = getNearbyAnchorPos(a,b,c, anchorList) dx,dy,dz = adjustAnchorVector(anchorId, spline, currentPos)--R5Utils.nodeRotationToVector(anchorId) else x,y,z = getSplinePosition(spline, currentPos) dx,dy,dz = getSplineDirection(spline, currentPos) end addXmlNode(numSc, x, y, z, dx, dy, dz) numSc = numSc +1 currentPos = currentPos + segmentSpacing/sLength end --get endcoord if snapToNearbyAnchor then local a,b,c = getSplinePosition(spline, 1) x,y,z, anchorId = getNearbyAnchorPos(a,b,c, anchorList) dx,dy,dz = adjustAnchorVector(anchorId, spline, 1)--R5Utils.nodeRotationToVector(anchorId) --dx = -dx -- negate x direction to match spline end direction else x,y,z = getSplinePosition(spline, 1) dx,dy,dz = getSplineDirection(spline, 1) end addXmlNode(numSc, x, y, z, dx, dy, dz) setXMLInt(posOutputXml, "SplineCoords.param#points", numSc+1) --write output to disk saveXMLFile(posOutputXml) print("Exported Spline Coords to:") print(xmlOutputPath..getName(spline)..".xml") -- Adjust TerrainHeight if setTerrainHeight then R5TerrainUtils.setTerrainHeight( -0.05, heightAdjustWidth/2, terrainRes ) print("Terrain-Adjust completed.") end --Terrain Layer Painting if paintTerrainTexture then R5TerrainUtils.paintTerrainBySpline( terrainLayerId, paintWidth/2, terrainRes ) print("Terrain-Painting completed.") end -- Foliage Layer Painting --Foliage Layer Painting if clearFoliage or drawSideFoliage then local drawWidth = roadWidth + 2*sideFoliageWith R5FoliageUtils.loadDensityMaps(pathFruitDensityGdm, pathGroundDensityGdm, forceReload) if clearFoliage then R5FoliageUtils.clearAllBySpline(spline, drawWidth) end if drawSideFoliage then R5FoliageUtils.drawLayerBySpline(spline, drawWidth, sideFoliageName, sideFoliageState) if drawInnerFoliage then drawWidth = roadWidth + 2*innerFoliageWith R5FoliageUtils.drawLayerBySpline(spline, drawWidth, innerFoliageName, innerFoliageState) end R5FoliageUtils.clearAllBySpline(spline, roadWidth) end print("Foliage-Painting completed.") end -- Reflector placement if placeReflectors then local placedObjects = createTransformGroup(getName(spline).."_Reflectors") link(roadsystem, placedObjects) local reflectorObj = R5Utils.searchNodeByName(roadsystem, reflGrpName) local prevX, prevY, prevZ = getSplinePosition(spline, 0) local splinePos = 0 --first copy: local x,y,z = getSplinePosition(spline, splinePos) local rx,ry,rz = getSplineOrientation(spline, splinePos, 0, -1, 0) local copy = clone(reflectorObj, false, true) link(placedObjects, copy) setTranslation(copy, x, y-0.025, z) setRotation(copy, rx,ry,rz) splinePos = splinePos + reflectorDistance / sLength while splinePos <= 1 do local x,y,z = getSplinePosition(spline, splinePos) local copy = clone(reflectorObj, false, true) link(placedObjects, copy) setTranslation(copy, x, y-0.05, z) -- fix rotation ensure updirection setDirection(copy,x-prevX,0,z-prevZ,0,1,0) rotateAboutLocalAxis(copy,math.pi*0/180,0,0,1) -- z rotateAboutLocalAxis(copy,math.pi*0/180,0,1,0) -- y rotateAboutLocalAxis(copy,math.pi*0/180,1,0,0) -- x -- updated prev positions prevX = x prevY = y prevZ = z splinePos = splinePos + reflectorDistance / sLength end print("Reflectors placed.") end print(">> SplineToCoord: done!") --[[ CHANGELOG =================================================== V 1.5.0: + added Foliage Layer Painting V 1.4.0: + added Terrain Layer Painting * optimisation and bugfixes V 1.3.1: * fixed direction-vector adjustment (crossproduct for vec-dir comparesion) V 1.3.0: + added reflector placement & terrain by spline height adjustment V 1.2.0: + added anchor direction-vector adjustment V 1.1.0: + added snap start/end to SplineAnchors + code optimisation ]]