Здравствуйте, gunf, Вы писали:
G>Здравствуйте.
G>Делаю 3D viewer на OpenGL и при наличии файла более 1.5 Мб (около 100 000 точек — рисую просто линии) — тормоза + 98% проца. G>Что можно сделать?
первое что приходит в голову — оптимизировать
рассакжи поподробнее как ты сейчас всё рисуешь...
Рисую так:
Пишу ну C++ Builder 5.
Сделал (делаю) компоненту на основе TCustomPanel — с OpenGL.
Вот кусок кода (2 функции) — где я рисую на панели:
//---------------------------------------------------------------------------
void __fastcall TMyPanel::PanelIdle(TObject*, bool& done)
{
done = false;
Paint();
}
//---------------------------------------------------------------------------
void __fastcall TMyPanel::Paint(void)
{
//TCustomPanel::Paint();
if (FOnPaint)
{
HPALETTE OldPalette=NULL;
if (Palette)
{
OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
{
ShowMessage("RealizePalette:"+IntToStr(GetLastError()));
return;
}
}
if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
{
ShowMessage("wglMakeCurrent:" + IntToStr(GetLastError()));
return;
}
FOnPaint(this);
if ((FSwapBuffers==Auto) && (DoubleBuffer))
::SwapBuffers(DisplayDeviceContext);
if (OldPalette)
wglMakeCurrent(NULL, NULL) ;
}
return;
}
//---------------------------------------------------------------------------
Функция PanelIdle — вызывается когда Application->OnIdle — простой. Делаю это для того, чтобы, например, при OnMouseWellDown (Up) — увеличивать масштаб и ets ...
В самой проге — использую компонент и гружу файл (текстовый с координатами~ 100 000 координат)
в событии OnPanelPaint вызываю glCallList в котором уже сформирована матрица с точками. Т.е.:
//---------------------------------------------------------------------------
void __fastcall TMain::PanelPaint(TObject *Sender)
{
Panel->Clear();
glCallList(List_Name);//ListName - список изображения
}
//---------------------------------------------------------------------------
А сам список формирую так:
List_Name = glGenLists(1);
glNewList(List_Name,GL_COMPILE);
Panel->SetPenColor(clRed);//Цвет пена
Panel->SetScreenColor(clWhite);//цвет фона
Panel->Mesh(Mesh);//финкция отрисовки сети см. ниже
glEndList();
//---------------------------------------------------------------------------
void __fastcall TMyPanel::Mesh (SURF matr)
{
for (int i = 0; i<int(matr.size()); i++)
{
for (int j = 1; j<int(matr[i].size()); j++)
{
glBegin(GL_LINES);
glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
glEnd();
}
}
}
//---------------------------------------------------------------------------
Вот в принципе и все.
Но 99 % проца — не есть весело
а что за видюха ?
ты точно дисплейный лист только один раз строишь при загрузке файла ?
и зачем wglMakeCurrent каждый раз вызывать ? у тебя несколько тредов чтоли ?
Здравствуйте, andy_k, Вы писали:
_>а что за видюха ? _>ты точно дисплейный лист только один раз строишь при загрузке файла ? _>и зачем wglMakeCurrent каждый раз вызывать ? у тебя несколько тредов чтоли ?
Видяха
NVIADIA GeForse 3 Ti 500
точно один раз.
wglMakeCurrent — вызываю тока один раз:
void __fastcall TMyPanel::Paint(void)
{
//TCustomPanel::Paint();
if (FOnPaint)
{
HPALETTE OldPalette=NULL;
if (Palette)
{
OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
{
ShowMessage("RealizePalette:"+IntToStr(GetLastError()));
return;
}
}
if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
{
ShowMessage("wglMakeCurrent:" + IntToStr(GetLastError()));
return;
}
FOnPaint(this);
if ((FSwapBuffers==Auto) && (DoubleBuffer))
::SwapBuffers(DisplayDeviceContext);
if (OldPalette)
wglMakeCurrent(NULL, NULL) ;
}
return;
оптимизировать имхо нужно здесь:
G>в событии OnPanelPaint вызываю glCallList в котором уже сформирована матрица с точками. Т.е.: G>
G>//---------------------------------------------------------------------------
G>void __fastcall TMain::PanelPaint(TObject *Sender)
G>{
G> Panel->Clear();
G> glCallList(List_Name);//ListName - список изображения
G>}
G>//---------------------------------------------------------------------------
G>
так как это функция мсполняется каждый кадр.
1. что делает Panel->Clear()?
2. точек действительно очень много. их все рисовать хоть glCallLists() хоть Vertex Array-ами — всё равно много. а выводить нужно все точки? может некая часть выходит из области видимости? тогда нужно копать в сторону усечений...
1. я бы сделал так
void __fastcall TMyPanel::Mesh (SURF matr)
{ glBegin(GL_LINES);
for (int i = 0; i<int(matr.size()); i++)
{
for (int j = 1; j<int(matr[i].size()); j++)
{
glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
}
} glEnd();
}
2. уточни — тормоза в коде по части OpenGL или в коде считывания данных из файла (почему бы не бинарник при такий объемах?) и их преобразования?
GРисую так
GПишу ну C++ Builder 5.
GСделал (делаю) компоненту на основе TCustomPanel — с OpenGL.
GВот кусок кода (2 функции) — где я рисую на панели
G[code]
G---------------------------------------------------------------------------
Gvoid __fastcall TMyPanelPanelIdle(TObject, bool& done)
G{
G done = false;
G Paint();
G}
G---------------------------------------------------------------------------
Gvoid __fastcall TMyPanelPaint(void)
G{
G TCustomPanelPaint();
G if (FOnPaint)
G {
G HPALETTE OldPalette=NULL;
G if (Palette)
G {
G OldPalette=SelectPalette(DisplayDeviceContext,Palette,FALSE);
G if (RealizePalette(DisplayDeviceContext)==GDI_ERROR)
G {
G ShowMessage(RealizePalette+IntToStr(GetLastError()));
G return;
G }
G }
G if (wglMakeCurrent(DisplayDeviceContext,GLRenderingContext)==false)
G {
G ShowMessage(wglMakeCurrent + IntToStr(GetLastError()));
G return;
G }
G FOnPaint(this);
G if ((FSwapBuffers==Auto) && (DoubleBuffer))
G SwapBuffers(DisplayDeviceContext);
G if (OldPalette)
G wglMakeCurrent(NULL, NULL) ;
G }
G return;
G}
G---------------------------------------------------------------------------
G[code]
GФункция PanelIdle — вызывается когда Application-OnIdle — простой. Делаю это для того, чтобы, например, при OnMouseWellDown (Up) — увеличивать масштаб и ets ...
1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит
G void __fastcall TMyPanelMesh (SURF matr)
G{
G for (int i = 0; iint(matr.size()); i++)
G {
G for (int j = 1; jint(matr[i].size()); j++)
G {
G glBegin(GL_LINES);
G glVertex3d(matr[i][j-1].x,matr[i][j-1].y,matr[i][j-1].z);
G glVertex3d(matr[i][j].x,matr[i][j].y,matr[i][j].z);
G glEnd();
G }
G }
G}
G[code]
2. а что это за структура такая SURF случаем обращение по индексам (matr[i][j-1]) — это не через свойства (с каким-нибудь кодом проверки индексов или еще чего)
З.Ы.
думаю — надо точно локализовать медленное место и оптимизировать его по максимуму
удачи
Здравствуйте, rikkitikkitavi, Вы писали:
R>1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит
А почему ты считаешь что такое не канает?
R>2. а что это за структура такая SURF случаем обращение по индексам (matr[i][j-1]) — это не через свойства (с каким-нибудь кодом проверки индексов или еще чего)
R>>1. я правильно понял, что на каждое событие OnIdle ты отрисовываешь свою графику xz имхо, такое никак не рулит G>А почему ты считаешь что такое не канает?
int nLines = 100;
int nPoints = 100;
double* matr = new double[nLines][nPoints];
...
for (int i=0; i<nLines; i++)
delete[] matr[i];
delete[] matr;
это должно значительно ускорить (т.к. прямое обращение к памяти)
написал на вскидку — на счет компилируемости не уверен, да и с уничтожением надо разобраться
да, вот еще что забыл — есть у меня компонент типа твоей панели, я ей пользовался, работает без проблем,,
если не хочешь изобретать велосипед, давай мыло — скину (откуда скачал не помню)
Здравствуйте, rikkitikkitavi, Вы писали:
G>>А почему ты считаешь что такое не канает?
R>1.потому что слишком часто вызывается. вспомни конвеер обработки сообщений
Я пробовал без Idle — все равно 99 % проца.
Жду компоненту — могет там как-то подругому сделано?
Здравствуйте, rikkitikkitavi, Вы писали:
G>>А почему ты считаешь что такое не канает?
R>1.потому что слишком часто вызывается. вспомни конвеер обработки сообщений
Я пробовал без Idle — все равно 99 % проца.
Жду компоненту — могет там как-то подругому сделано?
Здравствуйте, RikkiTikkiTavi, Вы писали:
RTT>Здравствуйте, gunf, Вы писали:
G>>Я пробовал без Idle — все равно 99 % проца. G>>Жду компоненту — могет там как-то подругому сделано?
RTT>на сколько я понял — тормозит при генерации display list, а не при отрисовке (это разные вещи)
не пойму я тогда — он что display list постоянно генерирует? его нужно сгенерировать однажды, а потом — рисовать сколько угодно... тогда имхо можно не заботится об эффективности кода его генерации — это ведь один раз происходит. а тормозит у нас — всЁ время. значит рисование надо оптимизировать!
вообщем вот какой вопрос "на засыпку" я имею ввиду:
зависит ли скорость рисования display list-а от кода его создвшего? (если суть сцены одинакова)
Здравствуйте, gunf, Вы писали:
G>Делаю 3D viewer на OpenGL и при наличии файла более 1.5 Мб (около 100 000 точек — рисую просто линии) — тормоза + 98% проца. G>Что можно сделать?
Линии как раз рисовать медленно. Обычно одна линия -- один треугольник.
А вообще, отсекай невидимые и слишком далекие грани. Ключевые слова: frustum culling, quadtree, octtree и т.п.
Плюс используй везде где возможно вертексные буферы (стандартное расширение ARB_vertex_buffer_object, доступно с OpenGL 1.4) или, хотя бы, дисплейные списки.
Почитай FAQи по performance'у. Только не слишком древние.