GLU NURBS отображается неправильно

РЕДАКТИРОВАТЬ: это ошибка библиотеки. Я сообщил об этом в список рассылки HOpenGL.

Я использую прямоугольный метод с 9 точками для представления круга/эллипса в виде NURBS.

Точки p1, p2, ..., p9, p9 = p1. Они лежат, как показано:

y2 | p2 p3 p4
y1 | p1    p5
y0 | p8 p7 p6
-------------
   | x0 x1 x2

x1 = (x0 + x2) / 2
y1 = (y0 + y2) / 2

т.е. p1 = (x0, y1), p2 = (x0, y2) и так далее.

И веса:

  • 1 для средних точек (p1,p3,p5,p7)
  • sqrt(0.5) для угловых точек (p2,p4,p6,p8)

Я применил веса как однородные координаты двумя способами:

  • справа - (x,y) с весом w становится Vertex4 (w*x) (w*y) 0 w
  • неправильно - становится Vertex4 x y 0 w

Результаты (сначала правильно, потом неправильно, извините, если они слишком большие): firstсекунда

Видите ли, оба не являются правильными кругами (хотя второй выглядит красиво), и я не могу понять, почему.

Ниже следует код, основанный на Lines.hs из примеров GLUT:

import System.Exit ( exitWith, ExitCode(ExitSuccess) )
import Graphics.UI.GLUT
import Foreign.Marshal.Array
import Graphics.Rendering.OpenGL.GLU.NURBS

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

display :: DisplayCallback
display = do
  clear [ ColorBuffer, DepthBuffer ]
  color (Color3 1.0 1.0 1.0 :: Color3 GLfloat)

  withNURBSObj () $ \nurbsObj -> do
    nurbsBeginEndCurve nurbsObj $
      withArrayLen knots $ \nKnots knots ->
        withArray controls $ \controls -> do
          nurbsCurve nurbsObj (fromIntegral nKnots) knots stride controls order

  flush

  where
    order = 3
    stride = 4 -- number of floats in Vertex
    controls = zipWith mkControl points weights
    mkControl (x, y) w = Vertex4 (x*w) (y*w) 0 w
    -- mkControl (x, y) w = Vertex4 x y 0 w
    knots = [0, 0, 0, 0.25, 0.25, 0.5, 0.5, 0.75, 0.75, 1, 1, 1]
    weights = let a = sqrt 0.5 in [1, a, 1, a, 1, a, 1, a, 1]
    points = [
      (x0, y1), (x0, y2), (x1, y2),
      (x2, y2), (x2, y1), (x2, y0),
      (x1, y0), (x0, y0), (x0, y1)
      ]

    y1 = (y0 + y2) / 2
    x1 = (x0 + x2) / 2
    (x0, x2) = (50, 450)
    (y0, y2) = (x0, x2)

reshape :: ReshapeCallback
reshape size@(Size w h) = do
   viewport $= (Position 0 0, size)
   matrixMode $= Projection
   loadIdentity
   ortho2D 0 (fromIntegral w) 0 (fromIntegral h)
   -- the following line is not in the original example, but it's good style...
   matrixMode $= Modelview 0

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

--  Request double buffer display mode.
--  Register mouse input callback functions
main :: IO ()
main = do
   (progName, _args) <- getArgsAndInitialize
   initialDisplayMode $= [ SingleBuffered, RGBMode ]
   initialWindowSize $= Size 500 500
   initialWindowPosition $= Position 100 100
   createWindow "Test"
   myInit
   displayCallback $= display
   reshapeCallback $= Just reshape
   keyboardMouseCallback $= Just keyboard
   mainLoop

РЕДАКТИРОВАТЬ: я перепроверил коэффициенты несколько раз, и перед прямоугольным представлением я использовал метод треугольника с 7 точками, и были очень похожие искажения. Так что с конкретным представительством проблем быть не должно.


person modular    schedule 17.10.2011    source источник
comment
Просто подсказка: вы должны изменить отображение на Int -> Int -> DisplayCallback, при этом первым параметром должен быть размер окна, а также установить всю проекцию в отображении. При изменении формы используйте каррирование displayCallback $= display w h; это делает его намного более похожим на Haskell, избегая ненужных примесей.   -  person datenwolf    schedule 17.10.2011
comment
ахах, сколько опечаток в одном комментарии, а отредактировать никак.   -  person datenwolf    schedule 18.10.2011


Ответы (1)


Хорошо, с моим первым ответом я на мгновение потерял рассудок. В любом случае, у вас вообще нет ошибки в вашем коде: если я скомпилирую и выполню данный код, я получу это:

NURBS круг

Я подозреваю, что что-то в вашей установке Haskell сломано.

ИЗМЕНИТЬ из-за комментария:

Теперь это странно…

Я использую Gentoo, поэтому моя система предлагает модули Haskell OpenGL через систему Portage. Таким образом я получаю это:

loki ~ # for p in OpenGL OpenGLRaw GLURaw; do ghc-pkg latest $p; done
OpenGL-2.2.1.1
ghc-pkg: cannot find package OpenGLRaw
ghc-pkg: cannot find package GLURaw

Поэтому я установил модули OpenGL и GLUT с помощью cabal в свой домашний каталог:

datenwolf@loki ~ $  for p in OpenGL OpenGLRaw GLURaw; do ghc-pkg latest $p; done
OpenGL-2.4.0.1
OpenGLRaw-1.1.0.1
GLURaw-1.1.0.0

И с этими установленными я могу воспроизвести вашу первую фотографию!

person datenwolf    schedule 17.10.2011
comment
О, это большое WTF для меня сейчас. Может быть, даже что-то не так с драйвером видеокарты. Большое спасибо, я опубликую обновление, когда узнаю причину. - person modular; 18.10.2011
comment
Можете ли вы написать свою платформу и версии пакетов OpenGL, GLURaw и, возможно, OpenGLRaw и GLUT? - person modular; 18.10.2011
comment
Вы можете запустить: for p in OpenGL OpenGLRaw GLURaw; do ghc-pkg latest $p; done - person modular; 18.10.2011