ЛЮДИ, разбирающиеся в С++ ХЕЛП

QweRius

Пользователь
День добрый,
Как упорядочить отрисовку объектов в opengl, тоесть чтобы дальние объекты не перекрывали ближние?
В коде:
Код:
void display () {
double diam_u=1.2, diam_f=1.2;
int n;
GLUquadricObj *quadObj;

quadObj = gluNewQuadric(); 
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_DEPTH_TEST);
gluQuadricDrawStyle(quadObj, GLU_FILL);
for (n=1; n<=1;n++ ) { 

GLfloat front_color[] = {1,1,1,1};
GLfloat back_color[] = {0,0,1,1};
glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);
glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);
glPushMatrix();


//U		
glColor3f ( 0.0f, 0.0f, 1.0f );
glTranslatef(x_u[n],y_u[n],z_u[n]);
gluSphere(quadObj, diam_u, 32, 32);
glPopMatrix();
//F1	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f1[n],y_f1[n],z_f1[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();
//F2	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f2[n],y_f2[n],z_f2[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();
//F3	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f3[n],y_f3[n],z_f3[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();
//F4	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f4[n],y_f4[n],z_f4[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();
//F5	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f5[n],y_f5[n],z_f5[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();

//F6	
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f6[n],y_f6[n],z_f6[n]);
gluSphere(quadObj, diam_f, 32, 32);
glPopMatrix();
}

glutSwapBuffers();
}
сфера F5, которая находится дальше, перекрывает две другие, которые находятся ближе, т.к рисуется позже. Как заставить отображаться объкты в нужном порядке изначально, а также, при повороте камеры? (для поворота использую gluLookAt)
 

sami

Местный
День добрый,
Как упорядочить отрисовку объектов в opengl, тоесть чтобы дальние объекты не перекрывали ближние?

сфера F5, которая находится дальше, перекрывает две другие, которые находятся ближе, т.к рисуется позже. Как заставить отображаться объкты в нужном порядке изначально, а также, при повороте камеры? (для поворота использую gluLookAt)
За упорядочивание по глубине в аппаратной графике типично отвечает буфер глубины. Если он не работает, то возможно в PIXELFORMAT не указан соответствующий параметр.
 

QweRius

Пользователь
За упорядочивание по глубине в аппаратной графике типично отвечает буфер глубины. Если он не работает, то возможно в PIXELFORMAT не указан соответствующий параметр.
тест глубины в main()
Код:
glClearDepth(1.0f);                
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
пробовал даже вызывать перед каждым новым объектом.
Про pixelformat можно поподробней? Либо, если не затруднит, ссылку, где можно почитать, применительно к opengl и linux.
А еще лучше, если наидется пример с использованием.
 

sami

Местный
тест глубины в main()
Код:
glClearDepth(1.0f);                
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
пробовал даже вызывать перед каждым новым объектом.
Про pixelformat можно поподробней? Либо, если не затруднит, ссылку, где можно почитать, применительно к opengl и linux.
А еще лучше, если наидется пример с использованием.
пикселформат это для винды. Для линуха похоже что glutInitDisplayMode.
 

sami

Местный
добавил в glutInitDisplayMode GLUT_DEPTH
картина покрылась непонятными пятнами, но порядок отрисовки не изменился:
Порядок отрисовки при наличии теста на глубину влияет только в режимах с нестрогим сравнением. Если сравнение строгое (а обычно используют его GL_LESS), то порядок не должен влиять.
Мне кажется, что какая-то путаница с координатами либо направлением gluLookAt.

Предлагаю взять рабочий пример и вставить код в него.
 

QweRius

Пользователь
В том то и дело, что если я "F6" ставлю в начало display(), он рисуется позади, если в конце, то спереди (координаты не трогаю).
С GL_LESS картинка еще хужеПосмотреть вложение 154153
Может с полным кодом будет проще?
#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>
#include <stdio.h>
#include <math.h>
#define elem_num 20


double
x_u[elem_num], x_f1[elem_num], x_f2[elem_num], x_f3[elem_num], x_f4[elem_num], x_f5[elem_num], x_f6[elem_num],
y_u[elem_num], y_f1[elem_num], y_f2[elem_num], y_f3[elem_num], y_f4[elem_num], y_f5[elem_num], y_f6[elem_num],
z_u[elem_num], z_f1[elem_num], z_f2[elem_num], z_f3[elem_num], z_f4[elem_num], z_f5[elem_num], z_f6[elem_num];
double
angle_vert, angle_hor, cam_step=2, cam_r=20, cam_x=0, cam_y=20, cam_z=0, polar[3];


void CamStart () {
polar[1]=20;
polar[2]=3870;
polar[3]=3600;
}

void CamPos () {
double CVlength, nx, ny, nz, up_x, up_y, up_z;

cam_x = polar[1]*sin(polar[2]*M_PI/180)*sin(polar[3]*M_PI/180);
cam_y = polar[1]*cos(polar[2]*M_PI/180);
cam_z = polar[1]*sin(polar[2]*M_PI/180)*cos(polar[3]*M_PI/180);
CVlength=sqrt(cam_x*cam_x+cam_y*cam_y+cam_z*cam_z);
nx=cam_x/CVlength;
ny=cam_y/CVlength;
nz=cam_z/CVlength;
up_x=-nx*ny;
up_y=nz*nz+nx*nx;
up_z=-nz*ny;
glLoadIdentity();
gluLookAt(cam_x,cam_y,cam_z,0,0,0,up_x,up_y,up_z);
}

void Camera(unsigned char key) {
if (key == 'q') {
polar[1] += cam_step;
CamPos();
}
if (key == 'e') {
polar[1] -= cam_step;
CamPos();
}
if (key == 'w') {
polar[2] += cam_step;
CamPos();
}
if (key == 's') {
polar[2] -= cam_step;
CamPos();
}
if (key == 'a') {
polar[3] += cam_step;
CamPos();
}
if (key == 'd') {
polar[3] -= cam_step;
CamPos();
}
if (key == '=') {
cam_step++;
printf("cam_step set to'%f'\n",cam_step);
}
if (key == '-') {
cam_step++;
printf("cam_step set to'%f'\n",cam_step);
}
if (key == '0') {
CamStart();
CamPos();
}
}

void SetCamera(unsigned char key, int x, int y) {
Camera(key);
}

void MolekCreate() {
double r_m=2;
x_u[1] = 0; y_u[1] = 0; z_u[1]=0;
x_f1[1] = -0.7*r_m; y_f1[1] = -0.7*r_m; z_f1[1]=-0.7*r_m;
x_f2[1] = 0.7*r_m; y_f2[1] = 0.7*r_m; z_f2[1]=0.7*r_m;
x_f3[1] = 0.7*r_m; y_f3[1] = -0.7*r_m; z_f3[1]=0.7*r_m;
x_f4[1] = -0.7*r_m; y_f4[1] = 0.7*r_m; z_f4[1]=-0.7*r_m;
x_f5[1] = 0.7*r_m; y_f5[1] = 0.0; z_f5[1]=-0.7*r_m;
x_f6[1] = -0.7*r_m; y_f6[1] = 0.0; z_f6[1]=0.7*r_m;

x_u[2] = 0; y_u[2] = 0; z_u[2]=0;
x_f1[2] = 2; y_f1[2] = 0; z_f1[2]=0;
x_f2[2] = -2; y_f2[2] = 0; z_f2[2]=0;
x_f3[2] = 0; y_f3[2] = 2; z_f3[2]=0;
x_f4[2] = 0; y_f4[2] = -2; z_f4[2]=0;
x_f5[2] = 0; y_f5[2] = 0; z_f5[2]=2;
x_f6[2] = 0; y_f6[2] = 0; z_f6[2]=-2;

x_u[3] = 0; y_u[3] = 0; z_u[3]=0;
x_f1[3] = 2; y_f1[3] = 0; z_f1[3]=0;
x_f2[3] = -2; y_f2[3] = 0; z_f2[3]=0;
x_f3[3] = 0; y_f3[3] = 2; z_f3[3]=0;
x_f4[3] = 0; y_f4[3] = -2; z_f4[3]=0;
x_f5[3] = 0; y_f5[3] = 0; z_f5[3]=2;
x_f6[3] = 0; y_f6[3] = 0; z_f6[3]=-2;

x_u[4] = 0; y_u[4] = 0; z_u[4]=0;
x_f1[4] = 2; y_f1[4] = 0; z_f1[4]=0;
x_f2[4] = -2; y_f2[4] = 0; z_f2[4]=0;
x_f3[4] = 0; y_f3[4] = 2; z_f3[4]=0;
x_f4[4] = 0; y_f4[4] = -2; z_f4[4]=0;
x_f5[4] = 0; y_f5[4] = 0; z_f5[4]=2;
x_f6[4] = 0; y_f6[4] = 0; z_f6[4]=-2;
}
void initDraw () {
//glEnable(GL_DEPTH_TEST);
//glDepthFunc(GL_LEQUAL);
}

void display () {
double diam_u=1.2, diam_f=1.2;
int n;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLUquadricObj *quadObj;
quadObj = gluNewQuadric();
gluQuadricDrawStyle(quadObj, GLU_FILL);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
for (n=1; n<=1;n++ ) {

GLfloat front_color[] = {1,1,1,1};
GLfloat back_color[] = {0,0,1,1};
glMaterialfv(GL_FRONT, GL_DIFFUSE, front_color);
glMaterialfv(GL_BACK, GL_DIFFUSE, back_color);

//U
glPushMatrix();
glColor3f ( 0.0f, 0.0f, 1.0f );
glTranslatef(x_u[n],y_u[n],z_u[n]);
gluSphere(quadObj, diam_u, 32, 32);
initDraw ();
glPopMatrix();
//F1
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f1[n],y_f1[n],z_f1[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();
//F2
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f2[n],y_f2[n],z_f2[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();
//F3
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f3[n],y_f3[n],z_f3[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();
//F4
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f4[n],y_f4[n],z_f4[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();
//F5
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f5[n],y_f5[n],z_f5[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();

//F6
glColor3f ( 0.0f, 1.0f, 0.0f );
glPushMatrix();
glTranslatef(x_f6[n],y_f6[n],z_f6[n]);
gluSphere(quadObj, diam_f, 32, 32);
initDraw ();
glPopMatrix();
}
glDisable(GL_DEPTH_TEST);

glutSwapBuffers();
}

void timer() {
display();
glutTimerFunc(100, timer, 0);
}

int main (int argc, char **argv) {
MolekCreate();
CamStart();
float pos[4] = {0,0,20,0.5};
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(400, 400);
glutInitWindowPosition(624, 100);
glutCreateWindow("UF6");

// Освещение
glEnable ( GL_COLOR_MATERIAL ) ;
glEnable(GL_LIGHTING);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_POSITION, pos);
glClearColor(0, 0, 0, 1.0);
//
glutDisplayFunc(display);
glutKeyboardFunc(SetCamera);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 0, 10.0);
glMatrixMode(GL_MODELVIEW);
CamPos();
timer(0);
glutMainLoop();
return 0;
}
 

sami

Местный
В том то и дело, что если я "F6" ставлю в начало display(), он рисуется позади, если в конце, то спереди (координаты не трогаю).
С GL_LESS картинка еще хужеПосмотреть вложение 154153
Может с полным кодом будет проще?
нет, с полным кодом проще не будет. Мне линуховую версию запустить не на чем. И лениво.
Да, порядок прорисовки влияет только с нестрогим неравенством. Судя по всему, проблема в буфере глубины. Или со значениями глубин при проекции. Такое ощущение, что все глубины ложатся около единицы.

Какие-нибудь примеры из интернета идут как надо?
 

QweRius

Пользователь
нет, с полным кодом проще не будет. Мне линуховую версию запустить не на чем. И лениво.
Да, порядок прорисовки влияет только с нестрогим неравенством. Судя по всему, проблема в буфере глубины. Или со значениями глубин при проекции. Такое ощущение, что все глубины ложатся около единицы.

Какие-нибудь примеры из интернета идут как надо?
Нашел !
Изначально взял пример из интернета, исправлял его под свои нужды. В результате удалил кусок кода, который не понимал и считал ненужным. Собственно все работало до этого момента, когда пришла необходимость сравнивать глубину.
Недостающим куском было:
Код:
static int g_Width = 600;                          // Initial window width
static int g_Height = 600;                         // Initial window height
static GLfloat g_nearPlane = 1;
static GLfloat g_farPlane = 1000;

in main () {
...
glutReshapeFunc (reshape);
...
}

void reshape(GLint width, GLint height)
{
g_Width = width;
g_Height = height;
glViewport(0, 0, g_Width, g_Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (float)g_Width / g_Height, g_nearPlane, g_farPlane);
glMatrixMode(GL_MODELVIEW);
}
Спасибо, извините, исправимся :)
 

QweRius

Пользователь
Как определяется максимальный размер массива в cpp?
Максимально возможный для long double, с которым успешно работала программа удалось создать.
long double A[4][7][100 000]
тоесть 4 x 7 x 100 000 = 2 800 000 ячеек и 2 800 000 * 8 байт = 2 МБ

Компилятор может создать и на 1 порядок больший массив (A[4][7][1 000 000]) , но программа уже работать отказывается, еще больше даже не пытается компилировать, сразу вываливается в ошибку про слишком "великий" размер.

Хотелось бы создать как минимум на два порядка больше...

зы. толькочто создал A[120 000 000] ~ 114МБ, правда при компиляции не хватило озу и заскрипел swap
Чем ему не нравится A[4][7][1 000 000] ~ 26МБ ? (а в идеале надо на 260МБ)
 

sami

Местный
Как определяется максимальный размер массива в cpp?
полагаю что максимальный размер определяется платформой/конкретным компилятором, т.к. в спецификации С++ нет даже точных указаний по поводу размеров примитивных типов данных кроме как для char.

Что-то плохо вы считаете, 4*7*1000000*8 ~ 220Мб

Так вы статический массив что ли выделяете такого размера? Динамически распределять не пробовали?
 

QweRius

Пользователь
Что-то плохо вы считаете, 4*7*1000000*8 ~ 220Мб
да, в последнем случае забыл домножить на 8.

Так вы статический массив что ли выделяете такого размера? Динамически распределять не пробовали?
Да, выделял статический массив, с динамическим массивом размер развернул во весь объём оперативной памяти, все ок, только в чем разница?
В моем случае каждый элемент массива содержит свою переменную, при этом размер массива постоянен. По-моему это логично создать статический массив. В добавок, где - то читал про уменьшение производительности программы, увеличение расходуемой памяти, при переходе от статических к динамичским из за двух обращений к памяти при динамическом массиве против одного при статическом.
 

sami

Местный
Да, выделял статический массив, с динамическим массивом размер развернул во весь объём оперативной памяти, все ок, только в чем разница?
Я не знаток C++ и особенностей его рантаймов.
В моем случае каждый элемент массива содержит свою переменную, при этом размер массива постоянен. По-моему это логично создать статический массив.
Не вполне. Запуск программы со значительным количеством статических данных может не быть успешным в разных окружениях. В них выполнение программы даже не начнется (управление не дойдет до main). В то время как программа, требующая динамических данных, при нехватке памяти просто завершится ошибкой. Но она и сможет ее обработать, т.е. написать в консоль о нехватке памяти.
В добавок, где - то читал про уменьшение производительности программы, увеличение расходуемой памяти, при переходе от статических к динамичским из за двух обращений к памяти при динамическом массиве против одного при статическом.
Про уменьшение производительности не выглядит правдоподобным, т.к. C++ о массиве "знает" лишь указатель на него. Природа указателя на статический массив точно такая же, как и на динамически выделенный массив.
Разница в производительности может быть лишь из-за самого выделения/освобождения памяти. Увеличение расходуемой памяти - разве что на размер служебной информации о выделенной памяти. Это лишь несколько байт.
 

QweRius

Пользователь
Не вполне. Запуск программы со значительным количеством статических данных может не быть успешным в разных окружениях. В них выполнение программы даже не начнется (управление не дойдет до main).
Похоже именно эта ситуация у меня имела место быть.

Разница в производительности может быть лишь из-за самого выделения/освобождения памяти. Увеличение расходуемой памяти - разве что на размер служебной информации о выделенной памяти. Это лишь несколько байт.
Правда, какогото значительного увеличения используемой памяти я не заметил.

Вот нашел, источник правда не надежный, но всеже:
На уровне процессора обращение к элементам статического массива a происходит так. Адрес начала массива известен еще при компиляции. Чтобы получить адрес элемента массива a, к адресу начала прибавляется индекс i, умноженный на размер одного элемента в байтах. Затем по вычисленному адресу идет обращение в память.

К элементам динамического массива получить доступ сложнее. На этапе компиляции адрес начала массива не известен. После выделения памяти он хранится в специальной переменной (указателе). Чтобы получить адрес элемента массива a, нужно сначала обратиться к памяти (взять значение указателя) и получить адрес начала массива. Потом к нему прибавить индекс, умноженный на размер элемента, и по вычисленному адресу элемента массива снова обратиться к памяти. Как видим, получается два обращения к памяти против одного у статических массивов.

http://written.ru/articles/technologies/programming/dynamic_and_static_arrays
 

sami

Местный
Вот нашел, источник правда не надежный, но всеже:

http://written.ru/ar...d_static_arrays
Довольно нелепое объяснение падения производительности аж на треть. Дело в том, что оптимизирующие компиляторы будут кэшировать адрес массива в регистре. В крайнем случае адрес массива будет лежать в кэше процессора, так что ходить за ним в память не придется.

Так же имеет значение, где именно расположена переменная с адресом массива. Если это глобальная переменная, то может потребоваться сходить за ней в память, если адрес массива передан в функцию параметром, то ходить за ним не надо будет.

В любом случае, лучше не теоретизировать, а провести замеры профайлером, или как минимум замерить время. Если разница будет существенна и стабильна, тогда там уж и поковыряться.
 

QweRius

Пользователь
Ну, гнаться за милисекундами и замерять лениво :). Работает и ладно, но за разъяснение, спасибо!
 

domenix

Активный пользователь
Я тоже удивлён что такой простой язык как С++ вызывает какие либо сложности ,ведь по нему столько литературы
например исчерпывающия все вопросы книга Бориса Похомова "C/C++ и MS Visual C++ 2008 для начинающих"(+CDROM c Microsoft Visual C++, Microsoft Visual Web Developer 2008 Express Edition,Microsoft Visual Basic 2008 Express Edition
хотя я лично предпочетаю assembler
 

sami

Местный
Я тоже удивлён что такой простой язык как С++ вызывает какие либо сложности ,ведь по нему столько литературы
например исчерпывающия все вопросы книга Бориса Похомова "C/C++ и MS Visual C++ 2008 для начинающих"(+CDROM c Microsoft Visual C++, Microsoft Visual Web Developer 2008 Express Edition,Microsoft Visual Basic 2008 Express Edition
хотя я лично предпочетаю assembler
C++ очень непростой язык. Невозможно исчерпать все вопросы С++ в одной книге. В случае, когда в названии книги фигурирует "для начинающих", на исчерпание всех вопросов особенно не стоит рассчитывать. Вы читали спецификацию языка? По объему она потянет на 12 типичных книг. Думаете, что спецификация исчерпывает все вопросы?
 
Сверху