- こちらがよいことに気づいた
- Stackを入れて、新しいプロジェクト "h170505"を作る
- 冒頭のサイトにも紹介されているOpenGLTutorial1をやってみる
- Main.hsの書き換え
- .../h170505/app/Main.hs を書き換える
import Graphics.UI.GLUT
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
mainLoop
display :: DisplayCallback
display = do
clear [ ColorBuffer ]
flush
stack install
-
- すると、エラーになる、GLUTが...と。
- 書き換えたMain.hsでimport Graphics.UI.GLUTしているのにそのことを.cabalファイルに教えていないから
- Main.hsで読んでいるパッケージなので、.../h170505/h170505.cabalファイルのMain.hsに対応して実行可能ファイルをつくるための欄を以下のように書き換える
executable h170505-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, h170505
, GLUT
, OpenGL
default-language: Haskell2010
stack install
h170505-exe
-
- Main.hsをさらに書き換え
- myPointsという GLfloatの3つ組のリストを用意し、それをリスト内包表現で12個の点として定義する
- その点座標からOpenGLが点として認識するらしきVertexに変える
- 変えるにあたり、すべての点にラムダ関数 (\始まり)をmapM_で適用する
import Graphics.UI.GLUT
myPoints :: [(GLfloat,GLfloat,GLfloat)]
myPoints = [ (sin (2*pi*k/12), cos (2*pi*k/12), 0) | k <- [1..12] ]
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
mainLoop
display :: DisplayCallback
display = do
clear [ColorBuffer]
renderPrimitive Points $
mapM_ (\(x, y, z) -> vertex $ Vertex3 x y z) myPoints
flush
-
- mapM_というmap関数の特殊形のようなものがなんだかわからないので調べることにする
- .../h170505/以下で
stack ghci
-
- とすると、現在の環境でのインターラクティブ版 ghciが現れるので
:type mapM_
mapM_ :: (Monad m, Foldable t) => (a -> m b) -> t a -> m ()
-
- とのこと
- "(\(x, y, z) -> vertex $ Vertex3 x y z)"が(a -> m b)
- "myPoints"がt a
- myPointsはリストなのでFoldable
- (x,y,z)はリストであるmyPointsの個々の要素で、3つ組
- 関数 vertex も:type vertex で調べると
:type vertex
vertex :: Vertex a => a -> IO()
-
- であり、VertexをIO()モナドに変える
- "$ Vertex3 x y z"は"(Vertex3 x y z)$"のことで、Vertex3 に3つの値を与えて作ったVertexを vertexに与えてIO()モナドにする
- 結局、モナド mのタプル () ができる
- 点の数を増やしてみる
- myKにInt型指定をして実行してみると、エラーが出る。myPointsの定義行ではFloatとして振舞っているから
- 型を指定せずにhaskellに型を選ばせておけばよい
import Graphics.UI.GLUT
myK = 120
myPoints :: [(GLfloat,GLfloat,GLfloat)]
myPoints = [ (sin (2*pi*k/myK), cos (2*pi*k/myK), 0) | k <- [1..myK] ]
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
mainLoop
display :: DisplayCallback
display = do
clear [ColorBuffer]
renderPrimitive Points $
mapM_ (\(x, y, z) -> vertex $ Vertex3 x y z) myPoints
flush
- renderPrimitive
- render Pointsというのは、mapM_が作る描図用のオブジェクトを個別に打点する
- render Trianglesとすると、3つずつを取り出して三角形を描く
import Graphics.UI.GLUT
myK = 12
myPoints :: [(GLfloat,GLfloat,GLfloat)]
myPoints = [ (sin (2*pi*k/myK), cos (2*pi*k/myK), 0) | k <- [1..myK] ]
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
mainLoop
display :: DisplayCallback
display = do
clear [ColorBuffer]
renderPrimitive Triangles $
mapM_ (\(x, y, z) -> vertex $ Vertex3 x y z) myPoints
flush
- 同様に…
- Triangles をTriangleStripに換えたり、TriangleFanに換えたりすれば、それぞれの仕様で表示される
- Lines, LikeLoop, LineStrip, Quads, QuadStrip, Polygon
- 色を試す
- display = doの内容を書き換えればいろいろできる
import Graphics.UI.GLUT
myK = 12
myPoints :: [(GLfloat,GLfloat,GLfloat)]
myPoints = [ (sin (2*pi*k/myK), cos (2*pi*k/myK), 0) | k <- [1..myK] ]
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
mainLoop
display :: DisplayCallback
display = do
let color3f r g b = color $ Color3 r g (b :: GLfloat)
vertex3f x y z = vertex $ Vertex3 x y (z :: GLfloat)
clear [ColorBuffer]
renderPrimitive Quads $ do
color3f 1 0 0
vertex3f 0 0 0
vertex3f 0 0.2 0
vertex3f 0.2 0.2 0
vertex3f 0.2 0 0
color3f 0 1 0
vertex3f 0 0 0
vertex3f 0 (-0.2) 0
vertex3f 0.2 (-0.2) 0
vertex3f 0.2 0 0
color3f 0 0 1
vertex3f 0 0 0
vertex3f 0 (-0.2) 0
vertex3f (-0.2) (-0.2) 0
vertex3f (-0.2) 0 0
color3f 1 0 1
vertex3f 0 0 0
vertex3f 0 0.2 0
vertex3f (-0.2) 0.2 0
vertex3f (-0.2) 0 0
flush
import Graphics.UI.GLUT
import Bindings
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
reshapeCallback $= Just reshape
keyboardMouseCallback $= Just keyboardMouse
mainLoop
-
- import Bindingsがなされている
- これは以下のような作成モジュールなので、stack new h170505して作った環境では、.../h170505/src/以下にBindings.hsとして配置する必要がある
module Bindings (display, reshape, keyboardMouse) where
import Graphics.UI.GLUT
import Display
reshape :: ReshapeCallback
reshape size = do
viewport $= (Position 0 0, size)
keyboardMouse :: KeyboardMouseCallback
keyboardMouse _key _state _modifiers _position = return ()
-
- このようにして置いたBindings.hsであるが、これだけでは、コンパイルしようとしても、見つからないので、h170505.cabalに書き込む。書き込む先は Library情報の場所。
- また、Bindings.hsでもGLUTをimportしている。GLUTをMain.hsで使うときに.cabalファイルを書き換えたが、Libraryのファイルの方にもこれを使うときには、そのことを別途.cabalに指定する
library
hs-source-dirs: src
exposed-modules: Lib
, Bindings
build-depends: base >= 4.7 && < 5
, GLUT
, OpenGL
default-language: Haskell2010
-
- さらに、Binding.hsの中身を見ると、import Displayしており、これも、以下のようなコードで作成し、src以下に置くので
module Display (display) where
import Graphics.UI.GLUT
import Cube
display :: DisplayCallback
display = do
clear [ColorBuffer]
cube 0.2
flush
-
- h170505.cabalにはさらに、このDiplayも追記して以下のようにする
library
hs-source-dirs: src
exposed-modules: Lib
, Bindings
, Display
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
library
hs-source-dirs: src
exposed-modules: Lib
, Bindings
build-depends: base >= 4.7 && < 5
, GLUT
, OpenGL
default-language: Haskell2010
-
- さらに、Diplay.hsを見るとCubeをimportしている。このCube.hsも作るので
module Cube where
import Graphics.UI.GLUT
cube :: GLfloat -> IO ()
cube w = do
renderPrimitive Quads $ do
vertex $ Vertex3 w w w
vertex $ Vertex3 w w (-w)
vertex $ Vertex3 w (-w) (-w)
vertex $ Vertex3 w (-w) w
vertex $ Vertex3 w w w
vertex $ Vertex3 w w (-w)
vertex $ Vertex3 (-w) w (-w)
vertex $ Vertex3 (-w) w w
vertex $ Vertex3 w w w
vertex $ Vertex3 w (-w) w
vertex $ Vertex3 (-w) (-w) w
vertex $ Vertex3 (-w) w w
vertex $ Vertex3 (-w) w w
vertex $ Vertex3 (-w) w (-w)
vertex $ Vertex3 (-w) (-w) (-w)
vertex $ Vertex3 (-w) (-w) w
vertex $ Vertex3 w (-w) w
vertex $ Vertex3 w (-w) (-w)
vertex $ Vertex3 (-w) (-w) (-w)
vertex $ Vertex3 (-w) (-w) w
vertex $ Vertex3 w w (-w)
vertex $ Vertex3 w (-w) (-w)
vertex $ Vertex3 (-w) (-w) (-w)
vertex $ Vertex3 (-w) w (-w)
library
hs-source-dirs: src
exposed-modules: Lib
, Bindings
, Display
, Cube
build-depends: base >= 4.7 && < 5
, GLUT
, OpenGL
default-language: Haskell2010
-
- となる
- 結局:
- Main.hsは.../h170505/app/以下にあって
import Graphics.UI.GLUT
import Bindings
main :: IO ()
main = do
(_progName, _args) <- getArgsAndInitialize
_window <- createWindow "Hello World"
displayCallback $= display
reshapeCallback $= Just reshape
keyboardMouseCallback $= Just keyboardMouse
mainLoop
-
- .../h170505/src/以下には、Bindings.hs,Diplay.hs,Cube.hsがあって
- h170505.cabalファイルは
name: h170505
version: 0.1.0.0
-- synopsis:
-- description:
homepage: https://github.com/githubuser/h170505#readme
license: BSD3
license-file: LICENSE
author: Author name here
maintainer: example@example.com
copyright: 2017 Author name here
category: Web
build-type: Simple
extra-source-files: README.md
cabal-version: >=1.10
library
hs-source-dirs: src
exposed-modules: Lib
, Bindings
, Display
, Cube
build-depends: base >= 4.7 && < 5
, GLUT
, OpenGL
default-language: Haskell2010
executable h170505-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, h170505
, GLUT
, OpenGL
default-language: Haskell2010
test-suite h170505-test
type: exitcode-stdio-1.0
hs-source-dirs: test
main-is: Spec.hs
build-depends: base
, h170505
ghc-options: -threaded -rtsopts -with-rtsopts=-N
default-language: Haskell2010
source-repository head
type: git
location: https://github.com/githubuser/h170505