meshprims.monkey2 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. Namespace mojo3d
  2. Private
  3. Function Editing:Bool()
  4. Return Scene.GetCurrent().Editing
  5. End
  6. Function AddInstance( instance:Mesh,ctor:String,args:Variant[] )
  7. Local scene:=Scene.GetCurrent()
  8. If scene?.Editing scene.Jsonifier.AddInstance( instance,ctor,args )
  9. End
  10. Struct TerrainData
  11. Field heightMap:Pixmap
  12. Field bounds:Boxf
  13. Field width:Int
  14. Field depth:Int
  15. Field iscale:Float
  16. Field jscale:Float
  17. Method GetPosition:Vec3f( i:Int,j:Int )
  18. Local x:=i*iscale
  19. Local z:=j*jscale
  20. Local y:=heightMap.PixelPtr( i,j )[0]/255.0
  21. Return New Vec3f( x,y,z ) * bounds.Size + bounds.min
  22. End
  23. Method GetTexCoord0:Vec2f( i:Int,j:Int )
  24. Return New Vec2f( i*iscale,j*jscale )
  25. End
  26. Method GetNormal:Vec3f( i:Int,j:Int )
  27. Local v0:=GetPosition( i,j )
  28. Local v1:=GetPosition( i,Min( j+1,depth-1 ) )
  29. Local v2:=GetPosition( Min( i+1,width-1 ),j )
  30. Local v3:=GetPosition( i,Max( j-1,0 ) )
  31. Local v4:=GetPosition( Max( i-1,0 ),j )
  32. Local n0:=(v1-v0).Cross(v2-v0).Normalize()
  33. Local n1:=(v2-v0).Cross(v3-v0).Normalize()
  34. Local n2:=(v3-v0).Cross(v4-v0).Normalize()
  35. Local n3:=(v4-v0).Cross(v1-v0).Normalize()
  36. Local n:=(n0+n1+n2+n3).Normalize()
  37. ' If (i&15)=0 And (j&15)=0 print "n="+v
  38. ' DebugAssert( n.y>0 )
  39. Return n
  40. End
  41. End
  42. Public
  43. #rem monkeydoc Extension methods for creating meshes.
  44. #end
  45. Class Mesh Extension
  46. Function CreateRect:Mesh( rect:Rectf )
  47. Local mesh:=New Mesh(
  48. New Vertex3f[](
  49. New Vertex3f( rect.min.x,rect.max.y,0 ),
  50. New Vertex3f( rect.max.x,rect.max.y,0 ),
  51. New Vertex3f( rect.max.x,rect.min.y,0 ),
  52. New Vertex3f( rect.min.x,rect.min.y,0 ) ),
  53. New UInt[](
  54. 0,1,2,
  55. 0,2,3 ) )
  56. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateRect",New Variant[]( rect ) )
  57. mesh.UpdateTangents()
  58. Return mesh
  59. End
  60. Function CreateBox:Mesh( box:Boxf,xsegs:Int=1,ysegs:Int=1,zsegs:Int=1 )
  61. Local vertices:=New Vertex3f[ ((ysegs+1)*(xsegs+1) + (zsegs+1)*(xsegs+1) + (ysegs+1)*(zsegs+1))*2 ],vp:=vertices.Data
  62. For Local q:=-1 To 1 Step 2
  63. For Local y:=0 To ysegs
  64. For Local x:=0 To xsegs
  65. Local vx:=box.Width*x/xsegs+box.min.x
  66. Local vy:=box.Height*y/ysegs+box.min.y
  67. vp[0]=New Vertex3f( vx,vy,q>0 ? box.max.z Else box.min.z, Float(x)/xsegs,Float(y)/ysegs, 0,0,q )
  68. vp+=1
  69. Next
  70. Next
  71. For Local z:=0 To zsegs
  72. For Local x:=0 To xsegs
  73. Local vx:=box.Width*x/xsegs+box.min.x
  74. Local vz:=box.Depth*z/zsegs+box.min.z
  75. vp[0]=New Vertex3f( vx,q>0 ? box.max.y Else box.min.y,vz, Float(x)/xsegs,Float(z)/zsegs, 0,q,0 )
  76. vp+=1
  77. Next
  78. Next
  79. For Local y:=0 To ysegs
  80. For Local z:=0 To zsegs
  81. Local vy:=box.Height*y/ysegs+box.min.y
  82. Local vz:=box.Depth*z/zsegs+box.min.z
  83. vp[0]=New Vertex3f( q>0 ? box.max.x Else box.min.x,vy,vz, Float(z)/zsegs,Float(y)/ysegs, q,0,0 )
  84. vp+=1
  85. Next
  86. Next
  87. Next
  88. Local indices:=New UInt[ (ysegs*xsegs + zsegs*xsegs + ysegs*zsegs) * 12 ],ip:=indices.Data,v0:=0
  89. For Local i:=0 To 1
  90. For Local y:=0 Until ysegs
  91. For Local x:=0 Until xsegs
  92. ip[0]=v0 ; ip[1+i]=v0+xsegs+2 ; ip[2-i]=v0+1
  93. ip[3]=v0 ; ip[4+i]=v0+xsegs+1 ; ip[5-i]=v0+xsegs+2
  94. ip+=6
  95. v0+=1
  96. Next
  97. v0+=1
  98. Next
  99. v0+=xsegs+1
  100. For Local z:=0 Until zsegs
  101. For Local x:=0 Until xsegs
  102. ip[0]=v0 ; ip[1+i]=v0+1 ; ip[2-i]=v0+xsegs+2
  103. ip[3]=v0 ; ip[4+i]=v0+xsegs+2 ; ip[5-i]=v0+xsegs+1
  104. ip+=6
  105. v0+=1
  106. Next
  107. v0+=1
  108. Next
  109. v0+=xsegs+1
  110. For Local y:=0 Until ysegs
  111. For Local z:=0 Until zsegs
  112. ip[0]=v0 ; ip[1+i]=v0+1 ; ip[2-i]=v0+zsegs+2
  113. ip[3]=v0 ; ip[4+i]=v0+zsegs+2 ; ip[5-i]=v0+zsegs+1
  114. ip+=6
  115. v0+=1
  116. Next
  117. v0+=1
  118. Next
  119. v0+=zsegs+1
  120. Next
  121. Local mesh:=New Mesh( vertices,indices )
  122. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateBox",New Variant[]( box,xsegs,ysegs,zsegs ) )
  123. mesh.UpdateTangents()
  124. Return mesh
  125. End
  126. Function CreateSphere:Mesh( radius:float,hsegs:Int=24,vsegs:Int=12 )
  127. Local vertices:=New Stack<Vertex3f>
  128. For Local i:=0 Until hsegs
  129. vertices.Push( New Vertex3f( 0,radius,0, (i+.5)/hsegs,0 ) )
  130. Next
  131. For Local i:=1 Until vsegs
  132. Local pitch:=i*Pi/vsegs-Pi/2
  133. For Local j:=0 To hsegs
  134. Local yaw:=(j Mod hsegs)*TwoPi/hsegs
  135. Local p:=Mat3f.Rotation( pitch,yaw,0 ).k * radius
  136. vertices.Push( New Vertex3f( p.x,p.y,p.z, Float(j)/hsegs,Float(i)/vsegs ) )
  137. Next
  138. Next
  139. For Local i:=0 Until hsegs
  140. vertices.Push( New Vertex3f( 0,-radius,0, (i+.5)/hsegs,1 ) )
  141. Next
  142. Local indices:=New Stack<UInt>
  143. For Local i:=0 Until hsegs
  144. indices.AddAll( New UInt[]( i,i+hsegs+1,i+hsegs ) )
  145. Next
  146. For Local i:=1 Until vsegs-1
  147. For Local j:=0 Until hsegs
  148. Local v0:=i*(hsegs+1)+j-1
  149. indices.AddAll( New UInt[]( v0,v0+1,v0+hsegs+2 ) )
  150. indices.AddAll( New UInt[]( v0,v0+hsegs+2,v0+hsegs+1 ) )
  151. Next
  152. Next
  153. For Local i:=0 Until hsegs
  154. Local v0:=(hsegs+1)*(vsegs-1)+i-1
  155. indices.AddAll( New UInt[]( v0,v0+1,v0+hsegs+1 ) )
  156. Next
  157. Local vdata:=vertices.Data
  158. For Local i:=0 Until vertices.Length
  159. vdata[i].normal=vdata[i].position.Normalize()
  160. Next
  161. Local mesh:=New Mesh( vertices.ToArray(),indices.ToArray() )
  162. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateSphere",New Variant[]( radius,hsegs,vsegs ) )
  163. mesh.UpdateTangents()
  164. Return mesh
  165. End
  166. Function CreateTorus:Mesh( outerRadius:Float,innerRadius:Float,outerSegs:Int=24,innerSegs:Int=12 )
  167. Local vertices:=New Vertex3f[ (outerSegs+1)*(innerSegs+1) ],vp:=vertices.Data
  168. For Local outer:=0 To outerSegs
  169. Local sweep:=Mat3f.Yaw( outer*TwoPi/outerSegs )
  170. For Local inner:=0 To innerSegs
  171. Local an:=inner*TwoPi/innerSegs
  172. Local cos:=Cos( an ),sin:=Sin( an )
  173. Local p:=sweep * New Vec3f( cos * innerRadius + outerRadius,sin * innerRadius,0 )
  174. Local t:=New Vec2f( Float(inner)/innerSegs,Float(outer)/outerSegs )
  175. Local n:=sweep * New Vec3f( cos,sin,0 )
  176. Local v:=New Vertex3f( p,t,n )
  177. vp[0]=v
  178. vp+=1
  179. Next
  180. Next
  181. Local indices:=New UInt[ outerSegs*innerSegs*6 ],ip:=indices.Data
  182. For Local outer:=0 Until outerSegs
  183. Local v0:=outer * (innerSegs+1)
  184. For Local inner:=0 Until innerSegs
  185. ip[0]=v0+innerSegs+1
  186. ip[2]=v0+innerSegs+2
  187. ip[1]=v0+1
  188. ip[3]=v0+innerSegs+1
  189. ip[5]=v0+1
  190. ip[4]=v0
  191. ip+=6
  192. v0+=1
  193. Next
  194. Next
  195. Local mesh:=New Mesh( vertices,indices )
  196. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateTorus",New Variant[]( outerRadius,innerRadius,outerSegs,innerSegs ) )
  197. mesh.UpdateTangents()
  198. Return mesh
  199. End
  200. Function CreateCylinder:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
  201. Local hlength:=length/2
  202. Local vertices:=New Stack<Vertex3f>
  203. Local triangles:=New Stack<UInt>
  204. 'tube
  205. For Local i:=0 To segs
  206. Local yaw:=(i Mod segs) * TwoPi / segs
  207. Local v:=New Vec3f( Cos( yaw ) * radius,hlength,Sin( yaw )* radius )
  208. Local n:=New Vec3f( v.x,0,v.z ).Normalize()
  209. Local tc:=New Vec2f( Float(i)/segs,0 )
  210. vertices.Add( New Vertex3f( v,tc,n ) )
  211. v.y=-v.y
  212. tc.y=1
  213. vertices.Add( New Vertex3f( v,tc,n ) )
  214. Next
  215. For Local i:=0 Until segs
  216. triangles.Add( i*2 ) ; triangles.Add( i*2+2 ) ; triangles.Add( i*2+3 )
  217. triangles.Add( i*2 ) ; triangles.Add( i*2+3 ) ; triangles.Add( i*2+1 )
  218. Next
  219. 'caps
  220. Local v0:=vertices.Length
  221. For Local i:=0 Until segs
  222. Local yaw:=i * TwoPi / segs
  223. Local v:=New Vec3f( Cos( yaw ) * radius,hlength,Sin( yaw ) * radius )
  224. Local n:=New Vec3f( 0,1,0 )
  225. Local tc:=New Vec2f( v.x*.5+.5,v.z*.5+.5 )
  226. vertices.Add( New Vertex3f( v,tc,n ) )
  227. v.y=-v.y
  228. n.y=-n.y
  229. vertices.Add( New Vertex3f( v,tc,n ) )
  230. Next
  231. For Local i:=1 Until segs-1
  232. triangles.Add( v0 ) ; triangles.Add( v0+(i+1)*2 ) ; triangles.Add( v0+i*2 )
  233. triangles.Add( v0+1 ) ; triangles.Add( v0+i*2+1 ) ; triangles.Add( v0+(i+1)*2+1 )
  234. Next
  235. Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
  236. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCylinder",New Variant[]( radius,length,axis,segs ) )
  237. Select axis
  238. Case Axis.X
  239. mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
  240. Case Axis.Z
  241. mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
  242. End
  243. mesh.UpdateTangents()
  244. Return mesh
  245. End
  246. Function CreateCapsule:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
  247. Const HalfPi:=Pi/2
  248. Local vertices:=New Stack<Vertex3f>
  249. Local triangles:=New Stack<UInt>
  250. Local t0:=HalfPi/radius/(length+HalfPi/radius)
  251. Local hlength:=length/2
  252. 'Top hemisphere
  253. '
  254. For Local i:=0 Until segs
  255. vertices.Add( New Vertex3f( 0,hlength+radius,0, (i+.5)/segs,0, 0,1,0 ) )
  256. Next
  257. For Local j:=1 To segs
  258. Local pitch:=j*Pi/(segs*2)-HalfPi
  259. For Local i:=0 To segs
  260. Local yaw:=(i Mod segs) * TwoPi / segs
  261. Local n:=Mat3f.Rotation( pitch,yaw,0 ).k
  262. Local v:=n*radius
  263. v.y+=hlength
  264. vertices.Add( New Vertex3f( v.x,v.y,v.z, Float(i)/Float(segs),Float(j)/Float(segs)*2*t0, n.x,n.y,n.z ) )
  265. Next
  266. Next
  267. For Local i:=0 Until segs
  268. triangles.Add( i ) ; triangles.Add( i+segs+1 ) ; triangles.Add( i+segs )
  269. Next
  270. For Local j:=1 Until segs
  271. For Local i:=0 Until segs
  272. Local t:=j*(segs+1)+i-1
  273. triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
  274. triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
  275. Next
  276. Next
  277. Local v0:=vertices.Length
  278. For Local j:=segs Until segs*2
  279. Local pitch:=j*Pi/(segs*2)-HalfPi
  280. For Local i:=0 To segs
  281. Local yaw:=(i Mod segs) * TwoPi / segs
  282. Local n:=Mat3f.Rotation( pitch,yaw,0 ).k
  283. Local v:=n*radius
  284. v.y-=hlength
  285. vertices.Add( New Vertex3f( v.x,v.y,v.z, Float(i)/Float(segs),(Float(j)/Float(segs*2)-.5)*2*t0, n.x,n.y,n.z ) )
  286. Next
  287. Next
  288. For Local i:=0 Until segs
  289. vertices.Add( New Vertex3f( 0,-hlength-radius,0, (i+.5)/segs,1, 0,-1,0 ) )
  290. Next
  291. For Local j:=0 Until segs-1
  292. For Local i:=0 Until segs
  293. Local t:=j*(segs+1)+i+v0
  294. triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
  295. triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
  296. Next
  297. Next
  298. For Local i:=0 Until segs
  299. Local t:=(segs+1)*(segs-1)+i+v0
  300. triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+1 )
  301. Next
  302. ' Join 2 bits together...
  303. '
  304. For Local i:=0 Until segs
  305. Local t:=segs*(segs+1)-1+i
  306. triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
  307. triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
  308. Next
  309. Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
  310. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCapsule",New Variant[]( radius,length,axis,segs ) )
  311. Select axis
  312. Case Axis.X
  313. mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
  314. Case Axis.Z
  315. mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
  316. End
  317. mesh.UpdateTangents()
  318. Return mesh
  319. End
  320. Function CreateCone:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
  321. Local hlength:=length/2
  322. Local vertices:=New Stack<Vertex3f>
  323. Local triangles:=New Stack<UInt>
  324. For Local i:=0 Until segs
  325. vertices.Add( New Vertex3f( 0,hlength,0, (i+.5)/segs,0, 0,1,0 ) )
  326. Next
  327. For Local i:=0 To segs
  328. Local yaw:=(i Mod segs) * TwoPi/segs
  329. Local n:=New Vec3f( Cos( yaw ),0,Sin( yaw ) )
  330. Local v:=New Vec3f( n.x*radius,-hlength,n.z*radius )
  331. Local tc:=New Vec2f( Float(i)/segs,1 )
  332. vertices.Add( new Vertex3f( v,tc,n ) )
  333. Next
  334. For Local i:=0 Until segs
  335. triangles.Add( i ) ; triangles.Add( i+segs+1 ) ; triangles.Add( i+segs )
  336. Next
  337. 'cap
  338. Local v0:=vertices.Length
  339. For Local i:=0 Until segs
  340. Local yaw:=i * TwoPi / segs
  341. Local n:=New Vec3f( Cos( yaw ),0,Sin( yaw ) )
  342. Local v:=New Vec3f( n.x*radius,-hlength,n.z*radius )
  343. Local tc:=New Vec2f( n.x*.5+.5,n.z*.5+.5 )
  344. vertices.Add( new Vertex3f( v,tc,n ) )
  345. Next
  346. For Local i:=1 Until segs-1
  347. triangles.Add( v0 ) ; triangles.Add( v0+i ) ; triangles.Add( v0+i+1 )
  348. Next
  349. Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
  350. If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCone",New Variant[]( radius,length,axis,segs ) )
  351. Select axis
  352. Case Axis.X
  353. mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
  354. Case Axis.Z
  355. mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
  356. End
  357. mesh.UpdateTangents()
  358. Return mesh
  359. End
  360. Function CreateTerrain:Mesh( heightMap:Pixmap,bounds:Boxf )
  361. Local width:=heightMap.Width
  362. Local depth:=heightMap.Height
  363. Local data:TerrainData
  364. data.heightMap=heightMap
  365. data.bounds=bounds
  366. data.width=width
  367. data.depth=depth
  368. data.iscale=1.0/(width-1)
  369. data.jscale=1.0/(depth-1)
  370. Local vertices:=New Vertex3f[ width*depth ]
  371. For Local j:=0 Until depth
  372. Local vp:=vertices.Data+j*width
  373. For Local i:=0 Until width
  374. vp[i].position=data.GetPosition( i,j )
  375. vp[i].texCoord0=data.GetTexCoord0( i,j )
  376. vp[i].normal=data.GetNormal( i,j )
  377. Next
  378. Next
  379. Local indices:=New UInt[ (width-1)*(depth-1)*6 ]
  380. local ip:=indices.Data
  381. For Local j:=0 Until depth-1
  382. Local v0:=j*width
  383. For Local i:=0 Until width-1
  384. ip[0]=v0+i ; ip[1]=v0+i+1+width ; ip[2]=v0+i+1
  385. ip[3]=v0+i ; ip[4]=v0+i+width ; ip[5]=v0+i+1+width
  386. ip+=6
  387. Next
  388. Next
  389. Local mesh:=New Mesh( vertices,indices )
  390. mesh.UpdateTangents()
  391. Return mesh
  392. End
  393. End
  394. #rem monkeydoc Extension methods for creating models.
  395. #end
  396. Class Model Extension
  397. Function CreateBox:Model( box:Boxf,xsegs:Int,ysegs:Int,zsegs:Int,material:Material,parent:Entity=Null )
  398. Local mesh:=mojo3d.Mesh.CreateBox( box,xsegs,ysegs,zsegs )
  399. Local model:=New Model( mesh,material,parent )
  400. Return model
  401. End
  402. Function CreateSphere:Model( radius:Float,hsegs:Int,vsegs:Int,material:Material,parent:Entity=Null )
  403. Local mesh:=mojo3d.Mesh.CreateSphere( radius,hsegs,vsegs )
  404. Local model:=New Model( mesh,material,parent )
  405. Return model
  406. End
  407. Function CreateTorus:Model( outerRadius:Float,innerRadius:Float,outerSegs:Int,innerSegs:Int,material:Material,parent:Entity=Null )
  408. Local mesh:=mojo3d.Mesh.CreateTorus( outerRadius,innerRadius,outerSegs,innerSegs )
  409. Local model:=New Model( mesh,material,parent )
  410. Return model
  411. End
  412. Function CreateCylinder:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
  413. Local mesh:=mojo3d.Mesh.CreateCylinder( radius,length,axis,segs )
  414. Local model:=New Model( mesh,material,parent )
  415. Return model
  416. End
  417. Function CreateCapsule:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
  418. Local mesh:=mojo3d.Mesh.CreateCapsule( radius,length,axis,segs )
  419. Local model:=New Model( mesh,material,parent )
  420. Return model
  421. End
  422. Function CreateCone:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
  423. Local mesh:=mojo3d.Mesh.CreateCone( radius,length,axis,segs )
  424. Local model:=New Model( mesh,material,parent )
  425. Return model
  426. End
  427. Function CreateTerrain:Model( heightMap:Pixmap,bounds:Boxf,material:Material,parent:Entity=Null )
  428. Local mesh:=mojo3d.Mesh.CreateTerrain( heightMap,bounds )
  429. Local model:=New Model( mesh,material,parent )
  430. Return model
  431. End
  432. End