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?
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;
