MKOverlayView и OpenGL

В момента имам UIView, който чертае радарни данни върху MKMapView с помощта на OpenGL. Поради нивото на детайлност на радарното изображение е необходим OpenGL (CoreGraphics не е достатъчно бърз).

Всички изображения, които рисувам, се записват в MKMapPoints. Избирам ги пред стандартните CLLocationCoordinate2D, защото дължините им не зависят от географската ширина. Основният метод за рисуване е следният:

  1. Добавете GLView като подизглед на MKMapView и задайте GLView.frame = MKMapView.frame.
  2. Използвайки GLOrthof, настройте проекцията на GLView да се равнява на текущия видим MKMapRect на картата. Ето кода, който прави това.

    CLLocationCoordinate2D coordinateTopLeft =
        [mapView convertPoint:CGPointMake(0, 0)
                 toCoordinateFromView:mapView];
    MKMapPoint pointTopLeft = MKMapPointForCoordinate(coordinateTopLeft);
    
    CLLocationCoordinate2D coordinateBottomRight =
        [mapView convertPoint:CGPointMake(mapView.frame.size.width,
                                          mapView.frame.size.height)
                 toCoordinateFromView:mapView];
    MKMapPoint pointBottomRight = MKMapPointForCoordinate(coordinateBottomRight);
    
    glLoadIdentity();
    glOrthof(pointTopLeft.x, pointBottomRight.x,
             pointBottomRight.y, pointTopLeft.y, -1, 1);
    
  3. Задайте прозореца за изглед на правилния размер, като използвате glViewport(0, 0, backingWidth, backingHeight), където backingWidth и backingHeight е размерът на mapView в точки.

  4. Начертайте с glDrawArrays. Не съм сигурен дали това има значение, но GL_VERTEX_ARRAY и GL_TEXTURE_COORD_ARRAY са активирани по време на тегленето.

С помощта на този метод всичко работи добре. Рисунката се изпълнява както трябва. Единственият проблем е, че тъй като това е подизглед на mapView (а не наслагване), радарното изображение се рисува върху всички други MKAnnotations и MKOverlays. Имам нужда този слой да бъде начертан под другите анотации и наслагвания.

Това, което се опитах да направя, за да накарам това да работи, беше да направя glView подизглед на персонализиран MKOverlayView вместо mapView. Това, което направих, беше да дам на MKOverlay boundingMapRect от MKMapRectWorld и да задам рамката на glView по същия начин, по който зададох проекцията (тъй като рамката на MKOverlayView се определя от MKMapPoints, а не от CGPoints). Отново, тук е кодът.

CLLocationCoordinate2D coordinateTopLeft =
    [mapView convertPoint:CGPointMake(0, 0)
             toCoordinateFromView:mapView];
MKMapPoint pointTopLeft = MKMapPointForCoordinate(coordinateTopLeft);

CLLocationCoordinate2D coordinateBottomRight =
    [mapView convertPoint:CGPointMake(mapView.frame.size.width,
                                      mapView.frame.size.height)
             toCoordinateFromView:mapView];
MKMapPoint pointBottomRight = MKMapPointForCoordinate(coordinateBottomRight);

glRadarView.frame = CGRectMake(pointTopLeft.x, pointTopLeft.y,
                               pointBottomRight.x - pointTopLeft.x,
                               pointBottomRight.y - pointTopLeft.y);

Когато направя това, glView се позиционира правилно на екрана (на същото място, което беше, докато беше подизглед на mapView), но чертежът вече не работи правилно. Когато изображението се появи, то не е с правилния размер и не е на правилното място. Направих проверка и backingWidth и backingHeight все още са размерът на изгледа в точки (както трябва да бъдат).

Някаква идея защо това не работи?


person Ross Kimes    schedule 07.01.2012    source източник
comment
Сигурни ли сте, че трябва да визуализирате радара в реално време? Предварителното изобразяване (напр. един включен PNG за всеки кадър) не е ли опция?   -  person    schedule 07.01.2012
comment
Кратък отговор, не. Има някои неща, които правя с данните (и още планирам да правя в актуализации), при които предварително изобразено изображение няма да работи.   -  person Ross Kimes    schedule 07.01.2012


Отговори (2)


Твърде дълго бях далеч от iphone, за да разбера напълно вашия код, но изглежда си спомням, когато преди време се забърках с Open GL на iPhone, открих, че е необходимо да поддържам собствения си z-индекс и просто начертайте елементи в този ред... Всяка операция по теглене се е завъртяла правилно в 3d, но нещо, начертано по-късно, винаги е било върху нещо, начертано по-рано. Една от ранните ми тестови програми начерта решетка върху повърхност и след това накара цялото нещо да се обърне. Очаквах решетката да изчезне, когато гърбът на обекта е обърнат към мен, но тя остана видима, защото беше начертана по-късно в отделна операция (IIRC)

Възможно е да съм правил нещо нередно, което е причинило този проблем, но моето решение беше да подредя тегленията си по z индекс.

Можете ли да нарисувате изображението първо, като използвате първия си метод?

person Gus    schedule 31.01.2012
comment
Не мисля, че това е проблемът. Рисувам само едно нещо и то е 2D рисунка. - person Ross Kimes; 31.01.2012
comment
Така че може би трябва да нарисувате 2 неща... Може би бихте могли да поставите текстура (с радара) върху правоъгълник с размера на екрана? iphonedevelopment.blogspot.com/2009/ 05/ ... След това можете да ги нарисувате в реда, който желаете. - person Gus; 31.01.2012
comment
Това е, което правя сега и работи. Частта, с която имам проблеми, е капсулирането на това в MKOverlayView. - person Ross Kimes; 01.02.2012

Мисля, че трябва просто да зададете прозореца за изглед, преди да зададете режима на прожектиране.

person c0d3rguy    schedule 01.02.2012
comment
Това също не изглежда да работи. Опитах да го имам преди директно преди glLoadIdentity() и между glLoadIdentity() и glOrthof(). - person Ross Kimes; 01.02.2012