How to set the movement of objects (pyramid and cube) so that they do not go at each other and move synchronously? That is, I need to make the house move (cube and pyramid) at the same time diagonally cube. My house is now spinning, and if I make it move relative to the cube diagonal, the roof and the base move relative to their points. Maybe it is possible to somehow group the two objects in OpenGL?

enter image description here

private bool textureIsLoad = false; public float rti, speed = 1,rotX,rotY,rotZ; public string texture_name = ""; public int imageId = 0; public string url; public uint mGlTextureObject = 0; public uint mGlTextureObject2 = 0; public Form1() { InitializeComponent(); AnT.InitializeContexts(); } private void Form1_Load(object sender, EventArgs e) { // ініціалізація бібліотеки Glut Glut.glutInit(); // ініціалізація режиму екрана Glut.glutInitDisplayMode(Glut.GLUT_RGB | Glut.GLUT_DOUBLE); // ініціалізація OpenGl Il.ilInit(); Il.ilEnable(Il.IL_ORIGIN_SET); // очиска екрана (RGBA) Gl.glClearColor(255, 255, 255, 1); // порт виводу Gl.glViewport(0, 0, AnT.Width, AnT.Height); // активація проекційної матриці Gl.glMatrixMode(Gl.GL_PROJECTION); // очистка матриці Gl.glLoadIdentity(); // перспектива Glu.gluPerspective(30, AnT.Width / AnT.Height, 1, 100); // обєктно видова матриця Gl.glMatrixMode(Gl.GL_MODELVIEW); Gl.glLoadIdentity(); // початкові настройкиOpenGL Gl.glEnable(Gl.GL_DEPTH_TEST); Gl.glEnable(Gl.GL_LIGHTING); Gl.glEnable(Gl.GL_LIGHT0); // активація таймера RenderTimer.Enabled = false; } private void RenderTimer_Tick(object sender, EventArgs e) { // промальовка Draw(); } private void Draw() { loadImage(); loadImage2(); // якщо текстура завантажена if (textureIsLoad) { // очистка буферів кольору та глибини Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); Gl.glClearColor(255, 255, 255, 1); // очищение вибраної матриці Gl.glLoadIdentity(); // вкл режим текстурування Gl.glEnable(Gl.GL_TEXTURE_2D); // ідентифікатор на текстурування mGlTextureObject Gl.glBindTexture(Gl.GL_TEXTURE_2D, mGlTextureObject); // зберігаємо матрицю Gl.glPushMatrix(); Gl.glTranslatef(0.0f, -0.5f, -7.0f); // поворот Gl.glRotatef(rti, 0.0f, 1.0f, 0.0f);//рух // рисуєм полігон Gl.glBegin(Gl.GL_QUADS); // малюєм куб //верх куба Gl.glLoadIdentity(); // перед Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Низ лліво Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(1.0f, -1.0f, 1.0f); // Низ право Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(1.0f, 1.0f, 1.0f); // Верх право Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Верх ліво // Зад Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-1.0f, -1.0f, -1.0f);// Низ право Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Верх право Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(1.0f, 1.0f, -1.0f); // Верх ліво Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(1.0f, -1.0f, -1.0f); // Низ ліво // Верх Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Верх ліво Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Низ ліво Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(1.0f, 1.0f, 1.0f); // Низ право Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(1.0f, 1.0f, -1.0f); // Верх право // Низ Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-1.0f, -1.0f, -1.0f);// Верх право Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(1.0f, -1.0f, -1.0f); // Верх ліво Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(1.0f, -1.0f, 1.0f); // Низ ліво Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Низ право // Права Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(1.0f, -1.0f, -1.0f); // Низ право Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(1.0f, 1.0f, -1.0f); // Верх право Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(1.0f, 1.0f, 1.0f); // Верх ліво Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(1.0f, -1.0f, 1.0f); // Низ ліво // Ліва Gl.glTexCoord2f(0.0f, 0.0f); Gl.glVertex3f(-1.0f, -1.0f, -1.0f);// Низ ліво Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(-1.0f, -1.0f, 1.0f); // Низ право Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-1.0f, 1.0f, 1.0f); // Верх право Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-1.0f, 1.0f, -1.0f); // Верх ліво Gl.glEnd(); Gl.glPopMatrix(); Gl.glFlush(); // повертаємо матрицю Gl.glPopMatrix(); //піраміда // замінюємо ідентифікатор текстури mGlTextureObject Gl.glBindTexture(Gl.GL_TEXTURE_2D, mGlTextureObject2); Gl.glPushMatrix(); Gl.glTranslatef(0.0f, 1.5f, -7.0f);//розміщення піраміди Gl.glRotatef(rti, 0.0f, 1.0f, 0.0f);//рух Gl.glBegin(Gl.GL_TRIANGLES); Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(0.0f, 1.0f, 0.0f); // верх піраміди Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-1.0f, -1.0f, 1.0f); // ліва Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(1.0f, -1.0f, 1.0f); // права Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(0.0f, 1.0f, 0.0f);//верх права Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(1.0f, -1.0f, 1.0f); // ліво (права) Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(1.0f, -1.0f, -1.0f); // права(право) Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(0.0f, 1.0f, 0.0f); // низ ззаду Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(1.0f, -1.0f, -1.0f); // ліва ззаду Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-1.0f, -1.0f, -1.0f); // права ззаду Gl.glTexCoord2f(1.0f, 0.0f); Gl.glVertex3f(0.0f, 1.0f, 0.0f); // верх ліво Gl.glTexCoord2f(1.0f, 1.0f); Gl.glVertex3f(-1.0f, -1.0f, -1.0f); // ліва ліво Gl.glTexCoord2f(0.0f, 1.0f); Gl.glVertex3f(-1.0f, -1.0f, 1.0f); // права ліво Gl.glEnd(); Gl.glPopMatrix(); Gl.glFlush(); Gl.glDisable(Gl.GL_TEXTURE_2D); rti += speed;//зміна шв руху // оновлюємо елемент зі сценою AnT.Invalidate(); } } private void loadImage() { // зображення з ідентифікатором imageId Il.ilGenImages(1, out imageId); // вибираєм зображення Il.ilBindImage(imageId); // адреса url = @"C:\Users\paliy\Documents\Visual Studio 2012\Projects\Grafica_2\text_stina.jpg"; // загружаєм if (Il.ilLoadImage(url)) { int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); // визначаєм число біт на піксель int bitspp = Il.ilGetInteger(Il.IL_IMAGE_BITS_PER_PIXEL); switch (bitspp) // від кількості біт { // GL_RGB або GL_RGBA case 24: mGlTextureObject = MakeGlTexture(Gl.GL_RGB, Il.ilGetData(), width, height); break; case 32: mGlTextureObject = MakeGlTexture(Gl.GL_RGBA, Il.ilGetData(), width, height); break; } textureIsLoad = true; // очищуємо память Il.ilDeleteImages(1, ref imageId); } } private static uint MakeGlTexture(int Format, IntPtr pixels, int w, int h) { // ідентифікатор текстурного обєкта uint texObject; // генеруємо текстурний обєкт Gl.glGenTextures(1, out texObject); // режим упаковки пікселів Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 1); // привязка до створеної текстури Gl.glBindTexture(Gl.GL_TEXTURE_2D, texObject); // режим фільтрації і повтору текстури Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); Gl.glTexEnvf(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_REPLACE); // RGB або RGBA switch (Format) { case Gl.GL_RGB: Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB, w, h, 0, Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, pixels); break; case Gl.GL_RGBA: Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, w, h, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, pixels); break; } // повертаємо ідентифікатор текстури return texObject; } //черепиця private void loadImage2() { // imageId Il.ilGenImages(1, out imageId); // вибироаєм збр Il.ilBindImage(imageId); // адрес string url = @"C:\Users\paliy\Documents\Visual Studio 2012\Projects\Grafica_2\texture_top.jpg"; if (Il.ilLoadImage(url)) { int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); int bitspp = Il.ilGetInteger(Il.IL_IMAGE_BITS_PER_PIXEL); switch (bitspp) { case 24: mGlTextureObject2 = MakeGlTexture(Gl.GL_RGB, Il.ilGetData(), width, height); break; case 32: mGlTextureObject2 = MakeGlTexture(Gl.GL_RGBA, Il.ilGetData(), width, height); break; } textureIsLoad = true; Il.ilDeleteImages(1, ref imageId); } } private static uint MakeGlTexture2(int Format, IntPtr pixels, int w, int h) { uint texObject; Gl.glGenTextures(2, out texObject); Gl.glPixelStorei(Gl.GL_UNPACK_ALIGNMENT, 1); Gl.glBindTexture(Gl.GL_TEXTURE_2D, texObject); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR); Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR); Gl.glTexEnvf(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_REPLACE); switch (Format) { case Gl.GL_RGB: Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB, w, h, 0, Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, pixels); break; case Gl.GL_RGBA: Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, w, h, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, pixels); break; } return texObject; } private void btnStart_Click(object sender, EventArgs e) { btnStart.Text = "Go"; //запуск таймера RenderTimer.Enabled = true; } private void btnPause_Click(object sender, EventArgs e) { //зупинка таймера RenderTimer.Enabled = false; btnStart.Text = "Continue"; } private void button1_Click(object sender, EventArgs e) { Application.Exit(); } private void trackBar1_Scroll(object sender, EventArgs e) { speed = (float)trackBar1.Value; label2.Text = Convert.ToString(speed); } } 

Here is an example of how I separately use the Gl.glRotatef () pyramid and cube;

  • Try using Display Lists - Dmitry Chistik
  • I did not get ... (I read that it is necessary to make movements of objects, and changes in their angle relative to X, Y, Z. but how to do this ( - Svyatoslav Palii

1 answer 1

You need to apply a general transformation to both objects. And without changing their local positions. This is done simply by multiplying the matrix. In your code, it might look like this:

  // очистка буферів кольору та глибини Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); Gl.glClearColor(255, 255, 255, 1); // очищение вибраної матриці Gl.glLoadIdentity(); // вкл режим текстурування Gl.glEnable(Gl.GL_TEXTURE_2D); // ідентифікатор на текстурування mGlTextureObject Gl.glBindTexture(Gl.GL_TEXTURE_2D, mGlTextureObject); // Ваш поворот Gl.glRotatef(rti, 0.0f, 1.0f, 0.0f);//рух // зберігаємо матрицю Gl.glPushMatrix(); Gl.glTranslatef(0.0f, -0.5f, -7.0f); // Тут поворот не нужен. // рисуєм полігон Gl.glBegin(Gl.GL_QUADS); .... Gl.glEnd(); Gl.glPopMatrix(); Gl.glFlush(); // повертаємо матрицю //Gl.glPopMatrix(); Возможно это лишнее //піраміда // замінюємо ідентифікатор текстури mGlTextureObject Gl.glBindTexture(Gl.GL_TEXTURE_2D, mGlTextureObject2); Gl.glPushMatrix(); Gl.glTranslatef(0.0f, 1.5f, -7.0f);//розміщення піраміди Gl.glBegin(Gl.GL_TRIANGLES); ... Gl.glPopMatrix(); Gl.glFlush(); ... 

I also think you have one Gl.glPopMatrix (); excess. Number of Gl.glPopMatrix (); must be equal to Gl.glPushMatrix ().

PS I see that you are using the old OpenGL. I recommend using OpenGL 3+.

  • But do not tell me how to make the movement of the object along the diagonal of the cube? - Svyatoslav Paliy
  • Apparently, instead of the transformation Gl.glRotatef (rti, 0.0f, 1.0f, 0.0f); // you need to apply the transformation Gl.glTranslatef (step, step, 0.0f); step should be increased for each render. - Unick
  • I was able to transform separately to a pyramid and a cube ... using Gl.glRotatef (); but now when I apply to the whole object for some reason I am not receiving ((( - Svyatoslav Paliy