я немного наверно не так сформулировал. Поверхность второго порядка надо построить, то есть Что касается ф-ии, то любую. Н-р по ссылке что я дал — гиперболойд обыкновенный можно взять за основу. Я просто думал есть уже спец ф-ия или какой то метод в opengl для прорисовки поверхностей 2 порядка.
Я такое же рисовал неделю назад Я вначале построил, то что хочу видеть с помощью Маткада и потом, по готовым функциям строил в Джеле кривую. У меня вышла обычная функция типа Z = sin(X)*sin(Y) (мне нужны были синусоидальные волны).
По поводу метода или спец функции пока ни чего не слышал. Может кто из умных людей заглянет и подскажет
Привет! Ниже привожу функцию, которой я рисую график функции Z = sin(X)*cos(Y): private void SinSin() { // prec_? - точность отображения поверхности. // Т.е. чем больше точность, тем более плавной // будет поверхность; int prec_x = 50, prec_y = 50, i = 0, j = 0; // Квадрат который отсекает поверхность по X и Y; int pole = 10; // Координаты точек поверхности; double[] X = new double[prec_x], Y = new double[prec_y]; double[,] Z = new double[prec_x, prec_y]; for (double x = 0; Math.Round(x, 4) < pole; x += (double)pole / (double)prec_x) { j = 0; X[i] = x; for (double y = 0; Math.Round(y,4) < pole; y += (double)pole / (double)prec_y) { Y[j] = y; // Ф-ция поверхности, которую будем отображать; Z[i, j] = Math.Sin(X[i]) * Math.Sin(Y[j]); j++; } i++; } // DRAWING. double r, g, b; r = g = b = 1.0f; for (i = 0; i < prec_x - 1; i++) { r = 1.0f; for (j = 0; j < prec_y - 1; j++) { // Рисуем поверхность треугольниками; Gl.glColor3d(r, g, b); Gl.glBegin(Gl.GL_TRIANGLES); // 1 Gl.glVertex3d(X[i], Z[i,j], Y[j]); Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); // 2 Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]); // End Gl.glEnd(); r -= 1.0 / prec_y; } g -= 1.0 / prec_x; } } Там конечно для нормального отображения нужно поворот сцены по осям сделать: Gl.glRotatef(30.0f, 1.0f, -1.0f, 0.0f); Если что-то непонятно, то пиши сюда.
то есть получается сначало математика, потом ты значения в матрицы записываешь, а потом матрицы воспроизводишь на сцене… Благодарствую. Буду разбираться…
В OpenGL всегда вначале математика Попробуй мой пример скопировать и запустить, поиграй с параметрами prec_x, prec_y и pole и ты увидишь, что к чему. Это не единственный вариант решения (надеюсь для построения графиков, но пока лучше я лично ни чего не придумал. Можно только цветовую раскраску, как вот вставить.
PS: не забываем плюсовать, если информация была полезной
Совсем забыл, можно использовать Джелевские массивы вершин, тогда отрисовка поверхности будет проходить быстрее: // Разрешаем использование массивов вершин; Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY); // Инициализируем точки вершин из массива; Gl.glVertexPointer(3, Gl.GL_FLOAT, 0, ARR_VERTEX); // Отрисовуем фигуру по точкам из памяти. Массив index // задает последовательность соединения точек в фигуру; Gl.glDrawElements(Gl.GL_TRIANGLES, index.Length, Gl.GL_UNSIGNED_INT, index); // Запрещаем массивы вершин; Gl.glDisableClientState(Gl.GL_VERTEX_ARRAY); Предварительно точки должны быть занесены в массив ARR_VERTEX и последовательность их соединения в массив index Т.е. при таком подходе мы не рисуем каждый треугольник отдельно (избегаем дублирование точек), как мы это сделали в функции SinSin(): for (i = 0; i < prec_x - 1; i++) { r = 1.0f; for (j = 0; j < prec_y - 1; j++) { // Рисуем поверхность треугольниками; Gl.glColor3d(r, g, b); Gl.glBegin(Gl.GL_TRIANGLES); // 1 Gl.glVertex3d(X[i], Z[i,j], Y[j]); Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); // 2 Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]); // End Gl.glEnd(); r -= 1.0 / prec_y; } g -= 1.0 / prec_x; } А сразу прорисовываем на экране всю поверхность одним вызовом Gl.glDrawElements
Просто при ответе на твой вопрос я привел не сложный пример, поэтому и не использовал GL_VERTEX_ARRAY
А если надо ф-ию нарисовать Z^2=X^2+Y^2? Я сделал у меня 2 массива Z,Z1 это верхняя парабола и нижняя. Только у меня как видно из картинки она какая то обрезанная пополам получилась. Як так?
Здравствуйте! Я не совсем понял, что именно нужно построить, график какой именно функции, но что касается Z^2=X^2+Y^2 могу объяснить. Все дело снова в математике, а именно в области определения функции: Область определения D(Z) = R, т.е. от -бесконечности до +бесконечности. Это означает, что функция определена для любых Х, а в случае 3-х мерного графика и для любых Y. Поэтому для корректного отображения графика функции Z^2=X^2+Y^2 необходимо брать промежуток по X, Y равный скажем [-pole; +pole]. А ты в своем примере как-бы ограничиваешь поверхность координатными осями X и Y.
Ниже привожу рабочий пример для рисования графика функции Z^2=X^2+Y^2: public void DrawFunction() { int prec_x = 50, prec_y = 50, i = 0, j = 0; int pole = 10; double[] X = new double[prec_x], Y = new double[prec_y]; double[,] Z = new double[prec_x, prec_y];
// Обрати внимание на условие цикла FOR for (double x = -pole; Math.Round(x, 4) < pole; x += (double)pole*2 / (double)prec_x) { j = 0; X[i] = x;
// Обрати внимание на условие цикла FOR for (double y = -pole; Math.Round(y, 4) < pole; y += (double)pole*2 / (double)prec_y) { Y[j] = y; // Ф-ция поверхности, которую будем отображать; //Z[i, j] = SinSin(X[i], Y[j]); Z[i, j] = Xpow2_Ypow2(X[i], Y[j]); j++; } i++; } // DRAWING. double r, g, b; r = g = b = 1.0f; for (i = 0; i < prec_x - 1; i++) { r = 1.0f; for (j = 0; j < prec_y - 1; j++) { // Рисуем поверхность треугольниками; Gl.glColor3d(r, g, b); Gl.glBegin(Gl.GL_TRIANGLES); // 1 Gl.glVertex3d(X[i], Z[i, j], Y[j]); Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); // 2 Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]); Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]); Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]); // End Gl.glEnd(); r -= 1.0 / prec_y; } g -= 1.0 / prec_x; } }
// Функция Z = sin(x)*sin(y); private double SinSin(double x, double y) { // z = Math.Sin(x) * Math.Sin(y); return Math.Sin(x) * Math.Sin(y); } При таких условиях в циклах FOR, получится следующее изображение:
Стоит ли переходить на Windows 10?Windows 10 установлена на каждый 3-й компьютер. Какие плюсы от перехода? DirectX 12 работает только в Windows 10?
Как установить Windows 10?Как бесплатно и легально скачать? Как записать и установить с последними обновлениями?
Сохраните страницу!
Регистрация
Регистрируясь, вы принимаете правила сайта. Если вы не получили код подтв. регистрации - не
забудьте проверить папку спам.
×
Восстановление пароля
Пожалуйста, заполните поля, после чего вы получите код подтверждения на ваш Email. Если код не пришел в течении нескольких минут - проверьте папку спам.
×
Авторизация
Авторизуйтесь с помощью соц. сети или с помощью аккаунта на сайте:
Что касается ф-ии, то любую. Н-р по ссылке что я дал — гиперболойд обыкновенный можно взять за основу. Я просто думал есть уже спец ф-ия или какой то метод в opengl для прорисовки поверхностей 2 порядка.
Я вначале построил, то что хочу видеть с помощью Маткада и потом, по готовым функциям строил в Джеле кривую. У меня вышла обычная функция типа Z = sin(X)*sin(Y) (мне нужны были синусоидальные волны).
По поводу метода или спец функции пока ни чего не слышал. Может кто из умных людей заглянет и подскажет
private void SinSin()
{
// prec_? - точность отображения поверхности.
// Т.е. чем больше точность, тем более плавной
// будет поверхность;
int prec_x = 50, prec_y = 50, i = 0, j = 0;
// Квадрат который отсекает поверхность по X и Y;
int pole = 10;
// Координаты точек поверхности;
double[] X = new double[prec_x], Y = new double[prec_y];
double[,] Z = new double[prec_x, prec_y];
for (double x = 0; Math.Round(x, 4) < pole;
x += (double)pole / (double)prec_x)
{
j = 0;
X[i] = x;
for (double y = 0; Math.Round(y,4) < pole;
y += (double)pole / (double)prec_y)
{
Y[j] = y;
// Ф-ция поверхности, которую будем отображать;
Z[i, j] = Math.Sin(X[i]) * Math.Sin(Y[j]);
j++;
}
i++;
}
// DRAWING.
double r, g, b;
r = g = b = 1.0f;
for (i = 0; i < prec_x - 1; i++)
{
r = 1.0f;
for (j = 0; j < prec_y - 1; j++)
{
// Рисуем поверхность треугольниками;
Gl.glColor3d(r, g, b);
Gl.glBegin(Gl.GL_TRIANGLES);
// 1
Gl.glVertex3d(X[i], Z[i,j], Y[j]);
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
// 2
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]);
// End
Gl.glEnd();
r -= 1.0 / prec_y;
}
g -= 1.0 / prec_x;
}
}
Там конечно для нормального отображения нужно поворот сцены по осям сделать:
Gl.glRotatef(30.0f, 1.0f, -1.0f, 0.0f);
Если что-то непонятно, то пиши сюда.
Попробуй мой пример скопировать и запустить, поиграй с параметрами prec_x, prec_y и pole и ты увидишь, что к чему. Это не единственный вариант решения (надеюсь для построения графиков, но пока лучше я лично ни чего не придумал. Можно только цветовую раскраску, как вот вставить.
PS: не забываем плюсовать, если информация была полезной
// Разрешаем использование массивов вершин;
Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
// Инициализируем точки вершин из массива;
Gl.glVertexPointer(3, Gl.GL_FLOAT, 0, ARR_VERTEX);
// Отрисовуем фигуру по точкам из памяти. Массив index
// задает последовательность соединения точек в фигуру;
Gl.glDrawElements(Gl.GL_TRIANGLES, index.Length,
Gl.GL_UNSIGNED_INT, index);
// Запрещаем массивы вершин;
Gl.glDisableClientState(Gl.GL_VERTEX_ARRAY);
Предварительно точки должны быть занесены в массив ARR_VERTEX и последовательность их соединения в массив index
Т.е. при таком подходе мы не рисуем каждый треугольник отдельно (избегаем дублирование точек), как мы это сделали в функции SinSin():
for (i = 0; i < prec_x - 1; i++)
{
r = 1.0f;
for (j = 0; j < prec_y - 1; j++)
{
// Рисуем поверхность треугольниками;
Gl.glColor3d(r, g, b);
Gl.glBegin(Gl.GL_TRIANGLES);
// 1
Gl.glVertex3d(X[i], Z[i,j], Y[j]);
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
// 2
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]);
// End
Gl.glEnd();
r -= 1.0 / prec_y;
}
g -= 1.0 / prec_x;
}
А сразу прорисовываем на экране всю поверхность одним вызовом Gl.glDrawElements
Просто при ответе на твой вопрос я привел не сложный пример, поэтому и не использовал GL_VERTEX_ARRAY
Я сделал у меня 2 массива Z,Z1 это верхняя парабола и нижняя. Только у меня как видно из картинки
она какая то обрезанная пополам получилась. Як так?
private void timer1_Tick(object sender, EventArgs e)
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
tick++;
Gl.glLoadIdentity();
Gl.glColor3f(1.0f, 0, 0);
Gl.glPushMatrix();
Gl.glTranslated(Global_x, Global_y, Global_z);
Gl.glRotated(Global_Rotated, 1, 1, 0);
Double pa = Global_pa, pb = Global_pb, pt = tick;
// prec_? - точность отображения поверхности.
// Т.е. чем больше точность, тем более плавной
// будет поверхность;
int prec_x = 50, prec_y = 50, i = 0, j = 0;
// Квадрат который отсекает поверхность по X и Y;
int pole = 10;
// Координаты точек поверхности;
double[] X = new double[prec_x], Y = new double[prec_y];
double[,] Z = new double[prec_x, prec_y];
double[,] Z1 = new double[prec_x, prec_y];
for (double x = 0; Math.Round(x, 4) < pole;
x += (double)pole / (double)prec_x)
{
j = 0;
X[i] = x;
for (double y = 0; Math.Round(y, 4) < pole;
y += (double)pole / (double)prec_y)
{
Y[j] = y;
// Ф-ция поверхности, которую будем отображать;
//Z[i, j] = Math.Sin(X[i]) * Math.Sin(Y[j]);
//Z[i, j] = Math.Sqrt((pa * pa * Math.Sin(pt) * Math.Sin(pt) * X[i] + pb * pb * Y[j] * Y[j]) / (pa * pa * pb * pb * Math.Sin(pt) * Math.Sin(pt))) - 1;
Z[i, j] =+Math.Sqrt(pa* X[i] * X[i] + pb*Y[j] * Y[j]);
Z1[i, j] = -Math.Sqrt(pa * X[i] * X[i] + pb * Y[j] * Y[j]);
j++;
}
i++;
}
// DRAWING.
double r, g, b;
r = g = b = 1.0f;
for (i = 0; i < prec_x - 1; i++)
{
r = 1.0f;
for (j = 0; j < prec_y - 1; j++)
{
// Рисуем поверхность треугольниками;
Gl.glColor3d(r, g, b);
Gl.glBegin(Gl.GL_TRIANGLES);
// 1
Gl.glVertex3d(X[i], Z[i, j], Y[j]);
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
// 2
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]);
// End
// 1
Gl.glVertex3d(X[i], Z1[i, j], Y[j]);
Gl.glVertex3d(X[i], Z1[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z1[i + 1, j], Y[j]);
// 2
Gl.glVertex3d(X[i], Z1[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z1[i + 1, j], Y[j]);
Gl.glVertex3d(X[i + 1], Z1[i + 1, j + 1], Y[j + 1]);
// End
Gl.glEnd();
r -= 1.0 / prec_y;
}
g -= 1.0 / prec_x;
}
Gl.glPopMatrix();
Gl.glFlush();
AnT.Invalidate();
}
Я не совсем понял, что именно нужно построить, график какой именно функции, но что касается Z^2=X^2+Y^2 могу объяснить.
Все дело снова в математике, а именно в области определения функции:
Область определения D(Z) = R, т.е. от -бесконечности до +бесконечности.
Это означает, что функция определена для любых Х, а в случае 3-х мерного графика и для любых Y. Поэтому для корректного отображения графика функции Z^2=X^2+Y^2 необходимо брать промежуток по X, Y равный скажем [-pole; +pole]. А ты в своем примере как-бы ограничиваешь поверхность координатными осями X и Y.
Ниже привожу рабочий пример для рисования графика функции Z^2=X^2+Y^2:
public void DrawFunction()
{
int prec_x = 50, prec_y = 50, i = 0, j = 0;
int pole = 10;
double[] X = new double[prec_x], Y = new double[prec_y];
double[,] Z = new double[prec_x, prec_y];
// Обрати внимание на условие цикла FOR
for (double x = -pole; Math.Round(x, 4) < pole;
x += (double)pole*2 / (double)prec_x)
{
j = 0;
X[i] = x;
// Обрати внимание на условие цикла FOR
for (double y = -pole; Math.Round(y, 4) < pole;
y += (double)pole*2 / (double)prec_y)
{
Y[j] = y;
// Ф-ция поверхности, которую будем отображать;
//Z[i, j] = SinSin(X[i], Y[j]);
Z[i, j] = Xpow2_Ypow2(X[i], Y[j]);
j++;
}
i++;
}
// DRAWING.
double r, g, b;
r = g = b = 1.0f;
for (i = 0; i < prec_x - 1; i++)
{
r = 1.0f;
for (j = 0; j < prec_y - 1; j++)
{
// Рисуем поверхность треугольниками;
Gl.glColor3d(r, g, b);
Gl.glBegin(Gl.GL_TRIANGLES);
// 1
Gl.glVertex3d(X[i], Z[i, j], Y[j]);
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
// 2
Gl.glVertex3d(X[i], Z[i, j + 1], Y[j + 1]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j], Y[j]);
Gl.glVertex3d(X[i + 1], Z[i + 1, j + 1], Y[j + 1]);
// End
Gl.glEnd();
r -= 1.0 / prec_y;
}
g -= 1.0 / prec_x;
}
}
// Функция Z^2 = X^2 + Y^2;
private double Xpow2_Ypow2(double x, double y)
{
// z = Math.Sqrt((x*x + y*y));
return Math.Sqrt((x*x + y*y));
}
// Функция Z = sin(x)*sin(y);
private double SinSin(double x, double y)
{
// z = Math.Sin(x) * Math.Sin(y);
return Math.Sin(x) * Math.Sin(y);
}
При таких условиях в циклах FOR, получится следующее изображение: