在 F# 中管理 DirectX

发布于 2022-09-09 11:02:12 字数 11859 浏览 23 评论 0

27073416_I5Sw.jpg (72.73 KB, 下载次数: 6)

下载附件

2011-02-12 16:45 上传

  1. #load @"BindAsLegacyV2Runtime.fs"
  2. // adjust these as needed for your latest installed version of ManagedDirectX
  3. #I @"C:WINDOWSMicrosoft.NETDirectX for Managed Code1.0.2902.0"
  4. #I @"C:WINDOWSMicrosoft.NETDirectX for Managed Code1.0.2903.0"  
  5. #I @"C:WINDOWSMicrosoft.NETDirectX for Managed Code1.0.2904.0"  
  6. #I @"C:WINDOWSMicrosoft.NETDirectX for Managed Code1.0.2907.0"  


  7. #r @"Microsoft.DirectX.dll"
  8. #r @"Microsoft.DirectX.Direct3D.dll"
  9. #r @"Microsoft.DirectX.Direct3Dx.dll"

  10. #load @"dxlib.fs"

  11. open System
  12. open System.Drawing
  13. open System.Windows.Forms
  14. open Microsoft.DirectX
  15. open Microsoft.DirectX.Direct3D
  16. open Microsoft.FSharp.Control.CommonExtensions
  17. open Sample.DirectX
  18. open Sample.DirectX.MathOps
  19. open Sample.DirectX.VectorOps

  20. let form = new SmoothForm(Visible = true, TopMost = true,
  21.                           Text = "F# surface plot",
  22.                           ClientSize = Size(600,400),
  23.                           FormBorderStyle=FormBorderStyle.FixedSingle)


  24. let renderer = new DirectXRenderer(form)

  25. renderer.DrawScene.Add(fun _ -> renderer.DrawCubeAxis())

  26. renderer.DrawScene.Add(fun _ -> renderer.SetupLights())



  27. let mutable view =
  28.    { YawPitchRoll   = Matrix.RotationYawPitchRoll(0.0f,0.0f,0.0f);
  29.      Focus          = scale 0.5f (X1 + Y1 + Z1);
  30.      Zoom           = 4.0 }

  31. renderer.DrawScene.Add(fun _ -> renderer.SetView(view))


  32. let mouseTrack = MouseTracker(form)

  33. mouseTrack.Add(fun (a,b) ->
  34.     let view2 =
  35.         let dx = b.X - a.X
  36.         let dy = b.Y - a.Y
  37.         match b.Button, Form.ModifierKeys with
  38.         | MouseButtons.Left, Keys.Shift -> view.AdjustZoom(dx,dy)
  39.         | MouseButtons.Left, _          -> view.AdjustYawPitchRoll(dx,dy)
  40.         | _                             -> view.AdjustFocus(dx,dy)  
  41.     view <- view2
  42. )

  43. let mutable ff    = (fun (t:float32) x y -> x * (1.0f - y))

  44. /// Z-range
  45. let mutable range = (0.0f,1.0f)

  46. /// XY-mesh
  47. let mutable mesh = BaseMesh.Grid(20,20)

  48. //mesh

  49. // Scale w.r.t. range ...
  50. let scalef (min,max) (z:float32) = (z-min) / (max-min)

  51. // Get the function and scale it
  52. let theFunction t x y = ff t x y |> scalef range

  53. renderer.DrawScene.Add(fun t -> renderer.DrawSurface mesh (theFunction t))

  54. //----------------------------------------------------------------------------
  55. // PART 2 - change the function

  56. ff <- (fun t x y -> sqr (x - 0.5f) * sqr (y - 0.5f) * 16.0f)
  57. ff <- (fun t x y -> 0.5f * sin(x * 4.5f + t / 2.0f) * cos(y * 8.0f) * x + 0.5f)

  58. range <- (-1.0f,1.0f)
  59. range <- (0.0f,1.0f)

  60. let ripple t x y =
  61.    let x,y = x - 0.5f,y - 0.5f
  62.    let r = sqrt (x*x + y*y)
  63.    exp(-5.0f * r) * sin(6.0f * pi * r + t) + 0.5f

  64. ff <- ripple

  65.   
  66. mesh <- BaseMesh.Grid (50,50)

  67. mesh <- BaseMesh.Grid (20,20)


  68. let surfacePoint f x y = Vector3(x,y,f x y)

  69. let surfaceNormal f x y =
  70.     let dx,dy = 0.01f,0.01f
  71.     let pA    = surfacePoint f x y
  72.     let pA_dx = surfacePoint f (x+dx) y - pA
  73.     let pA_dy = surfacePoint f x (y+dy) - pA
  74.     normalize (cross pA_dx pA_dy)

  75. let gravity = Vector3(0.0f,0.0f,-9.81f)

  76. // A ball is a pair of position/velocity vectors
  77. type ball = Ball of Vector3 * Vector3

  78. let radiusA = 0.010f
  79. let radiusB = 0.005f     

  80. let moveBall f timeDelta (Ball (position,velocity)) =

  81.    
  82.     let nHat     = surfaceNormal f position.X position.Y  

  83.     let acc      = planeProject nHat gravity              // acceleration in plane
  84.     let velocity = planeProject nHat velocity             // velocity     in plane
  85.    
  86.     // Compute the new position
  87.     let position = position + Vector3.Scale(velocity,timeDelta)  // iterate
  88.     let velocity = velocity + Vector3.Scale(acc     ,timeDelta)  // iterate

  89.     // Handle the bounce!
  90.     let bounce (p,v) =                                       
  91.         if   (p < 0.0f + radiusA) then (2.0f * (0.0f + radiusA) - p,-v)
  92.         elif (p > 1.0f - radiusA) then (2.0f * (1.0f - radiusA) - p,-v)
  93.         else                           (p,v)  
  94.     let px,vx = bounce (position.X,velocity.X)              // bounce X edges
  95.     let py,vy = bounce (position.Y,velocity.Y)              // bounce Y edges
  96.     let position = surfacePoint f px py                     // keep to surface
  97.     let velocity = Vector3 (vx,vy,velocity.Z)
  98.     let velocity = planeProject nHat velocity               // velocity in plane     

  99.     Ball (position,velocity)



  100. let drawBall t (Ball (p,v)) =
  101.     let n    = surfaceNormal (theFunction t) p.X p.Y
  102.     // position XY-projection
  103.     let p0   = Vector3(p.X,p.Y,0.0f)
  104.     // unit velocity XY-projection
  105.     let pV   = Vector3(v.X,v.Y,0.0f)                  
  106.     // and it's XY-perpendicular
  107.     let pVxZ = Vector3.Cross(pV,Z1)                        
  108.     // vertical line
  109.     renderer.DrawLines (Array.map (Vertex.Colored Color.Gray) [| p0;p |])
  110.     // velocity arrow on floor
  111.     renderer.DrawPlaneArrow Z1 p0 pV      
  112.     // normal arrow at point     
  113.     renderer.DrawPlaneArrow (cross n X1) p  (scale 0.8f n)
  114.     renderer.Device.Transform.World <-
  115.         (let m = Matrix.LookAtLH(p + scale radiusB n,p+n,X1)
  116.          Matrix.Invert(m))
  117.       
  118.     // Now draw the mesh
  119.     using (Mesh .Torus(renderer.Device,radiusB,radiusA,20,20)) (fun mesh ->
  120.         mesh.ComputeNormals()
  121.         mesh.DrawSubset(0))
  122.       
  123.     renderer.Device.Transform.World <- Matrix.Identity

  124. let mutable active = [] : ball list
  125. let addBall ball = active <- (ball :: active)  
  126. let drawBalls t =  active |> List.iter(drawBall t)
  127. let mutable timeDelta = 0.008f
  128. let moveBalls t =
  129.          let active' = active |> List.map (moveBall (theFunction t) timeDelta)
  130.          active <- active'

  131. //timeDelta <- 0.014f
  132. renderer.DrawScene.Add(fun t -> moveBalls t)
  133. renderer.DrawScene.Add(fun t -> drawBalls t)


  134. let bowl t x y =
  135.    let f phi u = ((1.0f + cos(2.0f * pi * u + phi )) / 2.0f)
  136.    f t x * f 0.0f y + 1.0f

  137. range <- (0.0f,2.0f)
  138. ff    <- (fun t -> bowl 0.0f)


  139. // Second, add a ball
  140. addBall (Ball (Vector3(0.1f,0.1f,0.1f),
  141.                Vector3(0.6f,0.5f,0.0f)))


  142. // Add a ball train.

  143. Async.Start
  144.     (async { for i in 0 .. 6 do
  145.                 do addBall (Ball (Vector3(0.1f,0.1f,0.1f),
  146.                                   Vector3(0.6f,0.5f,0.0f)))
  147.                 do! Async.Sleep(100)  })

  148. // Now move the floor!

  149. let mutable rate = 0.25f
  150. ff <- (fun t x y -> bowl (rate * t) x y)
  151. rate <- 1.0f
  152. rate <- 2.0f

  153. ff <- ripple
  154. range <- (0.0f,1.0f)

  155. mesh <- BaseMesh.Grid (30,30)

  156. #if COMPILED
  157. []
  158. do Application.Run(form)

  159. do Application.Exit()
  160. #endif
复制代码

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文