3

I write a program to visulize the electron cloud of hydrogen atom.

import System.Exit 
import Graphics.UI.GLUT
probDensity :: Double -> Double
probDensity r = abs $ (1 - r) * exp (-r/2.0)

myInit :: IO ()
myInit = clearColor $= Color4 1 1 1 0

grid :: [(GLint,GLint)]
grid = [(x,y) | x <- [-200..200],y <- [-200..200]]

density :: [Double]
density = map (\(i',j') -> probDensity $ sqrt $ (fromIntegral i' ** 2 + fromIntegral j' ** 2 ) / 324) grid

cloud = zip density grid

display :: DisplayCallback
display = do
  clear [ColorBuffer]

  color $ Color4 1 1 1 (0::GLfloat)
  renderPrimitive Points $
    mapM_ (\(c,(x,y)) -> color (Color3 c c 0) >> vertex (Vertex2 x y)) cloud
  flush

idle :: IdleCallback
idle = 
  postRedisplay Nothing


reshape :: ReshapeCallback
reshape (Size _ _) = do
   viewport $= (Position 0 0, Size 400 400)
   matrixMode $= Projection
   loadIdentity
   ortho2D (-200.0) 200.0 (-200.0) 200.0
   matrixMode $= Modelview 0
   loadIdentity

keyboard :: KeyboardMouseCallback
keyboard (Char '\27') Down _ _ = exitSuccess
keyboard _ _ _ _ = return ()


main :: IO ()
main = do
   (_, _args) <- getArgsAndInitialize
   initialDisplayMode $= [  RGBMode ]
   initialWindowSize $= Size 400 400
   initialWindowPosition $= Position 100 100
   _ <- createWindow "Cloud"
   shadeModel $= Smooth
   myInit
   displayCallback $= display 
   reshapeCallback $= Just reshape
   keyboardMouseCallback $= Just keyboard
   idleCallback $= Just idle
   mainLoop 

But the result has many lines on the right part of the graph. enter image description here

I checked my code again and again and could not find any faults. Is this a bug of the package?

iceiceice
  • 187
  • 1
  • 6

1 Answers1

5

I'd guess that this is because floating point error is causing certain columns to be missed during rasterization. You have 401 columns of samples spread over 400 columns of pixels, and your vertex positions are being sent as integers. When the integers get converted into floats in the graphics pipeline, they will not be exact. If you change your viewport and window size to something else, it should look fine:

399x399 :

enter image description here

400x400 :

enter image description here

401x401 (one-to-one pixel to sample):

enter image description here

402x402 :

enter image description here

Note, this also works fine if you increase the number of samples you're taking:

grid = [(x,y) | x <- [-400..400],y <- [-400..400]]
density = map (\(i',j') -> probDensity $ sqrt $
                           (fromIntegral i' ** 2 + fromIntegral j' ** 2 ) / 648) grid
renderPrimitive Points $
  mapM_ (\(c,(x,y)) -> do
    color (Color3 c c 0)
    vertex (Vertex2 (fromIntegral x / 2) (fromIntegral y / 2) :: Vertex2 GLfloat)) cloud

Another way to fix it is to target the pixel centers with float-valued vertex positions. Change

vertex (Vertex2 x y)

to

vertex (Vertex2 (fromIntegral x + 0.5) (fromIntegral y + 0.5) :: Vertex2 GLfloat)
Mokosha
  • 2,737
  • 16
  • 33
  • I just noticed that I really have 1 more sample than the number of columns. However, I think the last sample should just be discarded when it is out of the viewport. How could it cause such strange effects? – iceiceice Sep 10 '14 at 07:17
  • It's platform dependent how OpenGL chooses to round the vertex positions for point rendering. For example, on my mac, the code in your example renders fine as is. – Mokosha Sep 10 '14 at 07:31
  • A digress. I used a list for the points to be rendered, and the list grid contains more than 160000 elements. I am worried about the performance because as we all know the list will become a monster when its length gets long. But as far as I know the opengl seems to only support list. Does haskell opengl supports array or something else? – iceiceice Sep 10 '14 at 08:49
  • Yes it does. What you're using here is what's known as [Immediate mode](http://stackoverflow.com/questions/6733934/what-does-immediate-mode-mean-in-opengl) OpenGL which has been deprecated for almost a decade. Haskell has a lot of support for arrays that can be used as pointers in [modern OpenGL](http://www.arcsynthesis.org/gltut/) – Mokosha Sep 10 '14 at 14:55