понедельник, 11 января 2016 г.

Cars by roads

Скрипт расставляет машины по дорогам.
- умеет менять плотность машин (с помощью omni lights -> Near Attenuation)
- проецировать машины на дороги со сложным рельефом
- умет работать с прилинкованными объектами к машинам (например люди в салоне и т.п.)

Данный скрипт полезен, когда надо быстро расставить машины по изогнутым, рельефным дорогам.


Пример работы (spline надо сконвертировать в editable spline):

Проецирование на поверхность



------------------------------start
-- tested in 3DMax 2014
--units:  1 Unit = 1 Centimeters
try destroyDialog CarsBySpline catch()

--global variables
global CarsBySpline
global LengthSeg = 0
global arrTrafficOmni = #()
global arrSplineData = #()
global theMainMesh = undefined
global theMainSelectionCars = #()
global TempArraysCarsForDelete = #()  

  
--functions  
fn filter_spline o = superclassof o == shape --filter only shapes
fn filter_Mesh o = superclassof o == GeometryClass --filter only shapes
  
fn NormPlanter ArrObj theRoad = (
  if ArrObj.count >0 and theRoad != undefined and superclassof theRoad == GeometryClass do( 
        tempMesh = snapshot theRoad
        for i in ArrObj do(  
            theObj = i
            theObjT = theObj.transform
            theIntRay = intersectRay tempMesh (Ray [theObjT[4].x, theObjT[4].y, theRoad.max.z + 1000] [0,0,-1])
            if theIntRay != undefined do(  
                NaprVecX = theObjT[1]
                NaprVecY = theObjT[2]

                x0 = theIntRay.pos.x
                y0 = theIntRay.pos.y
                z0 = theIntRay.pos.z
              
                x1 = theObjT[4][1]
                y1 = theObjT[4][2]
                z1 = theObjT[4][3]
              
                l = NaprVecX[1]
                m = NaprVecX[2]
                n = NaprVecX[3]
              
                A1 = y1*n-y0*n-z1*m+z0*m
                B1 = -x1*n+x0*n+z1*l-z0*l      
                C1 = x1*m-x0*m-y1*l+y0*l

                A2 = theIntRay.dir[1]
                B2 = theIntRay.dir[2]  
                C2 = theIntRay.dir[3]  

            --napravlayshiy vector peresecheniya dvuh ploskostey
                DirVX = [B1*C2 - B2*C1, C1*A2 - C2*A1, A1*B2 - A2*B1]
                DirVX =if (dot DirVX NaprVecX) > 0 then DirVX else -DirVX
                nDirVX = normalize DirVX
              
                DirVY = cross nDirVX theIntRay.dir
                DirVY = if (dot DirVY NaprVecY) > 0 then DirVY  else -DirVY
                nDirVY = normalize DirVY
              
                theNewX = nDirVX
                theNewY = nDirVY
                theNewZ = theIntRay.dir
                theNewPos = theIntRay.pos
              
                theObj.transform = (matrix3 theNewX theNewY theNewZ theNewPos)
                )--END if theIntRay != undefined do
            ) -- END for i in ArrObj do
            delete tempMesh
        ) -- END if ArrObj.count >0 and theGround != undefined do
    )

  
fn instanceCar FlipAxis theSh rb1_state distMin distMax densCars arrNum  =
(
    if FlipAxis then (tM1 = 1; tM2 = 0) else (tM1 = 0; tM2 = 1)
    LengthSeg += length(arrSplineData[arrNum] - arrSplineData[arrNum-1])
    if LengthSeg >= (random distMin distMax) do
    (
        LengthSeg = 0
        if (random 0 100) <= densCars do
        (
            --instance  new car
            GetRandomCar = theMainSelectionCars[random 1 theMainSelectionCars.count]
            maxops.clonenodes GetRandomCar cloneType:#instance expandHierarchy:true newNodes:&nnl
            new_car = nnl[1]
            join TempArraysCarsForDelete nnl
          
            --transform
            case rb1_state of
                (
                    1: (
                            theY = normalize (arrSplineData[arrNum - tM2] - arrSplineData[arrNum - tM1])
                            theZ = [0,0,1]
                            theX = cross theY theZ
                            new_car.transform = matrix3 theY theX theZ (arrSplineData[arrNum] + theY*(random -theSh theSh))
                        )
                    2: (
                            theY = normalize (arrSplineData[arrNum - tM2] - arrSplineData[arrNum - tM1])
                            theZ = [0,0,1]
                            theX = cross theY theZ
                            new_car.transform = matrix3 theX theY theZ (arrSplineData[arrNum] + theX*(random -theSh theSh))
                        )
                )
            -- planting to mesh
            if theMainMesh != undefined do NormPlanter #(new_car) theMainMesh
            )
        )
      
    )

fn getOmniByZone_Point mPoint arrOmni =
(
    local arrO = arrOmni
    local arrDataProc = #()
    for o in arrOmni do
    (
            local theDist = distance mPoint o.pos
            local procDist = (theDist - o.nearAttenStart)/(o.nearAttenEnd - o.nearAttenStart)
            append arrDataProc procDist
        )
    local NumOmni = findItem arrDataProc (amin arrDataProc)
    return arrO[NumOmni]  
    )
  
----END functions  


--Interface
rollout CarsBySpline "Cars by Spline"
(  
group "Selection:"
(
    listbox ListCars ""  height:10
    button addToListCars "Add cars to list" width:175

    listbox ListTraffic ""  height:2
    button addToListTraffic "Add OMNI as traffic light" width:175  
    label lbl1 ""
    pickbutton chooseShape "Select road spline" width:175 filter:filter_spline
    pickbutton chooseMesh "SelectRoadMesh(not necessarily)" width:175 filter:filter_Mesh
    )
group "Parameters:"
    (
    spinner DistCarsMin "DistanceCars-MIN:" range:[501,10000000, 550] type:#integer width:120 align:#right --across:2
    spinner DistCarsMax "DistanceCars-MAX:" range:[0,10000000, 4000] type:#integer width:120 align:#right
    spinner theShift "Shift:" range:[0,1000, 70] type:#integer width:70 align:#right
    spinner densityCars "Density of cars:" range:[0,100, 30] type:#float width:120 align:#right
    spinner AccurRead "Step of reading spline:"  range:[10,1000, 30] type:#float width:120 align:#right
    checkbox DelCars "Delete OLD"    checked:true align:#right
    label lbl2 "Direction objects by:"
    radiobuttons rb1  "" labels:#("X", "Y") default:2 across:2 align:#center
    checkbox theFlip "Flip"    checked:false align:#center
        )

button theGo "Execute" width:175 height:30  align:#left  --across:2

on CarsBySpline open do
    (
        global LengthSeg = 0
        global arrTrafficOmni = #()
        global arrSplineData = #()
        global theMainMesh = undefined
        global theMainSelectionCars = #()
        global TempArraysCarsForDelete = #()
        )
      
      

      
on addToListTraffic pressed do(
    arrTrafficOmni = for i in selection where classOf i == Omnilight collect i
    local ListName = #()
    if arrTrafficOmni.count != 0 then(
            for i in arrTrafficOmni do append ListName i.name
            ListTraffic.items = ListName
            ) else ListTraffic.items = #()
    )  
  
 on addToListCars pressed do(
    theMainSelectionCars = for i in selection collect i
    local ListName = #()
    if theMainSelectionCars.count != 0 then(
            for i in theMainSelectionCars do append ListName i.name
            ListCars.items = ListName
            ) else ListCars.items = #()
     )

on chooseShape picked main_spl do
(
    chooseShape.text = main_spl.name

--reading data of shape  
    arrSplineData = #()
    for numS = 1 to (numSplines  main_spl) do
        (   
            progressstart "Reading splines..."  
            for k =0.0 to 1.0 by (
                if AccurRead.value/(getSegLengths main_spl numS)[(getSegLengths main_spl numS).count] < 0.0001 then 0.0001
                else AccurRead.value/(getSegLengths main_spl numS)[(getSegLengths main_spl numS).count]
                )    do (
                         append arrSplineData (pathInterp main_spl numS k)
                         progressupdate (k*100.0)
                            )
            progressend ()
        ) -- END for numS = 1 to (numSplines  theMainShape) do
)


on chooseMesh picked obj do (chooseMesh.text = obj.name; theMainMesh = obj)

on theGo pressed do
(
    max select none
    if DelCars.state do (try(delete TempArraysCarsForDelete)catch();TempArraysCarsForDelete = #())      
  
    if arrSplineData.count >= 2 and theMainSelectionCars.count > 0  then
    (
        if arrTrafficOmni.count > 0 then
        (
            for i = 2 to arrSplineData.count do
            (
                --vibor omni po velichine vliyaniya
                mainOmni = getOmniByZone_Point arrSplineData[i] arrTrafficOmni
          
                if (distance arrSplineData[i] mainOmni.pos) > mainOmni.nearAttenEnd do instanceCar theFlip.state theShift.value rb1.state DistCarsMin.value DistCarsMax.value densityCars.value i
                if (distance arrSplineData[i] mainOmni.pos) < mainOmni.nearAttenStart do instanceCar theFlip.state theShift.value rb1.state 500.0 650.0 100.0 i
              
                if (distance arrSplineData[i] mainOmni.pos) < mainOmni.nearAttenEnd and (distance arrSplineData[i] mainOmni.pos) > mainOmni.nearAttenStart do
                (
                    procDist = ((distance arrSplineData[i] mainOmni.pos) - mainOmni.nearAttenStart)/(mainOmni.nearAttenEnd - mainOmni.nearAttenStart)
                  
                    theMin = DistCarsMin.value + (DistCarsMin.value - 500)*procDist
                    theMax = DistCarsMax.value + (DistCarsMax.value - 650)*procDist
                    theDensity = 100.0 - (100.0 - densityCars.value)*procDist
                  
                    instanceCar theFlip.state theShift.value rb1.state theMin theMax theDensity i
                    )
                ) --END for i = 2 to arrSplineData.count do
            )else for i = 2 to arrSplineData.count do instanceCar theFlip.state theShift.value rb1.state DistCarsMin.value DistCarsMax.value densityCars.value i
        )else (print "No data")

)-- END on theGo pressed do


) --END rollout
createDialog CarsBySpline width:200
-- Created Alex Yakushev (alexander.yakushev@gmail.com, aly.work@mail.ru)

------------------------------end

Комментариев нет:

Отправить комментарий