-- 我不习惯MAXSCRIPT 的函数规范!!!!!!! 非常令人讨厌!!!! --global test_res = false; --global test_pt = #(); fn SYPointinpolygon = ( local i ; return i; -- b = selectbitmap() -- return undefined ) -- 我们需要获得包围盒,在包围盒内部取随机点,这样速度要快得多 fn SYCreateForest = ( --debug = newScript() local terrain = undefined for i = 1 to rootnode.children.count do ( if ( rootnode.children[i].name == "sy_terrain" ) then ( terrain = rootnode.children[i] break ) ) if(terrain == undefined) then ( messagebox "不存在地形对象." return undefined ) local XSize = getuserprop terrain "SY_XSize" local YSize = getuserprop terrain "SY_YSize" local GirdSize = getuserprop terrain "SY_TerrGrid" if(XSize == undefined or YSize == undefined or GirdSize == undefined ) then ( messagebox "地形对象不合法,缺少自定义参数." return undefined ) local TerrLeft = -(XSize/2)*GirdSize; local TerrTop = -(YSize/2)*GirdSize; local objectfilename = getuserprop SYCurTreeShape "SY_SrcFile" if(objectfilename == undefined) then ( messagebox("植被模型不合法,缺少自定义参数.") return undefined ) local NumVerts = SYCurBoundShape.numverts --format "NumVerts :% \n" NumVerts to:debug -- 计算AA包围盒 local BMin = point3 999999.0 999999.0 999999.0; local BMax = point3 -999999.0 -999999.0 -999999.0; for i = 1 to NumVerts do ( local pos = meshOP.getVert SYCurBoundShape i if(pos.x > BMax.x) then ( BMax.x = pos.x ) if(pos.x < BMin.x) then ( BMin.x = pos.x ) if(pos.y > BMax.y) then ( BMax.y = pos.y ) if(pos.y < BMin.y) then ( BMin.y = pos.y ) ) --format "Bound: Min % % Max % % \n" BMin.x BMin.y BMax.x BMax.y to:debug local checkmintrans = 0; local checkmaxtrans = 0; if(SYTransMin.x >0.00001 or SYTransMin.y >0.00001) then ( checkmintrans = 1; ) if(SYTransMax.x > SYTransMin.x or SYTransMax.y > SYTransMin.y) then ( checkmaxtrans = 1; ) if(SYTransMax.x < SYTransMin.x) then ( SYTransMax.x = SYTransMin.x; ) if(SYTransMax.y < SYTransMin.y) then ( SYTransMax.y = SYTransMin.y; ) -- 强制不做距离检查 -- checkmintrans = 0; -- checkmaxtrans = 0; local cachedpos = Point3 0 0 0; if( terrain != undefined ) then ( --format "start % \n" terrain.name to:debug local pt = Point3 0 0 0; local rot = Point3 0 0 0 ; local scl = Point3 0 0 0 ; local ok = false local TreeList = #() local x0 = 0.0; local x1 = 0.0; local x2 = 0.0; local x3 = 0.0; local y0 = 0.0; local y1 = 0.0; local y2 = 0.0; local y3 = 0.0; local ElipseA = 0.0; local ElipseB = 0.0; for T =1 to SYTreeCount do ( ok = 0; while( ok != 1 ) do ( -- 我们需要改进随机算法,思路是在一个环形区域内进行采样,然后再进行拒绝选择. -- 但是基于脚本提供的数学功能和效率支持,最终决定选择一种更简单快速的逼近算法. if( checkmintrans == 1 or checkmaxtrans == 1) then ( if(cachedpos.x == 0 AND cachedpos.y == 0) then ( pt.x = random BMin.x BMax.x pt.y = random BMin.y BMax.y )else ( --format "Cached Pos :% %\n" cachedpos.x cachedpos.y to:debug local theta = random -180 180 ElipseA = random SYTransMin.x SYTransMax.x ElipseB = random SYTransMin.y SYTransMax.y -- format "Elipse A B :% %\n" ElipseA ElipseB to:debug -- format "theta :% \n" theta to:debug local cost = cos theta local sint = sin theta -- format "cost sint :% %\n" cost sint to:debug local pt_x = ElipseA * cost as float; local pt_y = ElipseB * sint as float; -- format "pt_x pt_y :% %\n" pt_x pt_y to:debug pt.x = cachedpos.x as float + pt_x as float; pt.y = cachedpos.y as float + pt_y as float; --format "random pt :% %\n" pt.x pt.y to:debug ) )else ( pt.x = random BMin.x BMax.x pt.y = random BMin.y BMax.y ) --format "pt :% %\n" pt.x pt.y to:debug local Seg = NumVerts as integer -1; local i; local j = Seg ; local Start = Point3 0 0 0; local End = Point3 0 0 0; local test = 0; local factor = float 0.1; for i = 1 to Seg do ( Start = meshOP.getVert SYCurBoundShape i End = meshOP.getVert SYCurBoundShape j -- 判断交点 if( (Start.y < pt.y and End.y > pt.y) or (Start.y > pt.y And End.y < pt.y)) then ( factor = pt.y as float - Start.y as float; factor = factor / (End.y as float - Start.y as float) --format "pass 0 : \n" NumVerts to:debug if ( (Start.x + factor*(End.x as float -Start.x)) < pt.x) then ( --format "pass 1 : \n" NumVerts to:debug if(test == 1) then ( test = 0 ) else ( test = 1 ) ) ) j = i as integer ) ok = test as integer; if(ok == 1) then ( -- format "Found % % :\n" pt.x pt.y to:debug -- 检查最小距离,最大距离. for treept in TreeList do ( local diff = pt as Point3 - treept as Point3; if(checkmintrans == 1) then ( if (diff.x < SYTransMin.x or diff.y < SYTransMin.y) then ( format "Min Check Diff :% %\n" diff.x diff.y to:debug ok = 0; ) ) if(ok == 1 AND checkmaxtrans == 1) then ( if(diff.x > SYTransMax.x or diff.y > SYTransMax.y) then ( format "Max Check Diff :% %\n" diff.x diff.y to:debug ok = 0 ) ) ) ) if(ok == 1) then ( append TreeList pt; cachedpos = pt; ) ) --format "found pt :[% , %] \n" pt.x pt.y to:debug -- 我们现在需要获得Z -- ceil floor ??? local txi = (pt.x - TerrLeft)/GirdSize; local tyi = (pt.y - TerrTop)/GirdSize; txi = txi as integer; tyi = tyi as integer; --local txi2 = txi +1; --local tyi2 = tyi +1; local tpos = meshOP.getVert terrain (txi + tyi*XSize +1) -- 简单地放置在地形顶点上 mergemaxfile objectfilename #select local Object = $ if(Object == undefined) then ( messagebox "unknown error! please contact P.K." title:"Sunyou Plugin" ) Object.name = uniquename SYCurTreeShape.name setUserProp Object "SY_SrcFile" objectfilename Object.rotation.controller.X_Rotation = random SYRotMin.x SYRotMax.x -- Object.rotation.controller.Y_Rotation = random SYRotMin.y SYRotMax.y Object.rotation.controller.Z_Rotation = random SYRotMin.z SYRotMax.z Object.pos = tpos Object.scale.x = random SYScaleMin.x SYScaleMax.x Object.scale.y = random SYScaleMin.y SYScaleMax.y Object.scale.z = random SYScaleMin.z SYScaleMax.z ) )else ( messagebox "地形不存在!" ) )