gpt4 book ai didi

c++ - 在 OpenGL 中使用等 ionic 分形生成地形

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:15:44 27 4
gpt4 key购买 nike

我想使用等 ionic 分形生成随机地形。我正在浏览 Internet 以找到可以帮助我解决特定问题的解决方案,但没有找到任何东西。事实上,我生成了如下所示的简单等 ionic 分形:

这是分形的图片:

fractal

分形并不完美,因为有看到正方形但被我的老师接受。生成这种分形的算法是,给定一个输入正方形,我通过在每个正方形边的中间插入四个点,然后在中心插入一个点,将其分成较小的正方形,从而创建 4 个新正方形。每个新生成的顶点都有它的颜色值,它是一个范围为 [0, 255] 的 float ,它是使用特殊公式计算的。我现在的任务是使用这个分形生成随机地形,并且知道每个点的高度与计数的颜色值成正比。我的问题是我尝试使用生成的正方形角坐标绘制四边形,但我的四边形没有连接(有些地方两个四边形边缘的高度不同,以至于它们之间出现间隙)。

这是我的地形图:

terrain

这是我生成这个地形的代码:

#include <iostream>
#include "glut\glut.h"
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <fstream>

int window_width = 600, window_height = 600;
typedef float point2d[2];
struct vertex;
struct square;
std::vector<square> sq; // generated squares

// represents the vertex in 2 D
struct vertex
{
point2d pos;
float c;
};

// represents square in 2D
struct square
{
square() {}
square(vertex x, vertex y, vertex z, vertex w) : a(x), b(y), c(z), d(w)
{
this->x = abs(y.pos[0] - x.pos[0]);
}
vertex a, b, c, d;
float x; // length of the side of the square
};
// deklaracje funkcji glut:
void display_scene();
void reshape(GLsizei width, GLsizei height);
void key_pressed(unsigned char key, int x, int y);

// helper function used when counting color of
// newly generated verticle (point)
float W(float x)
{
return (-1.0 / window_width)*x + (float)(1.0 / 2.0);
}

// the same as above but for middle point
float Wc(float x)
{
return ((-1.0 / 1200.0f)*x + (float)(1.0 / 2.0)) / 2;
}

// converts value of range [0.0, 255.0] to
// the numeber of range [0.0, 1.0]
float rgb_to_float(float rgb)
{
return (1.0f / 255.0f) * rgb;
}

// gets color for a vertex based on the newly created
// square's side length x
float get_color(float c1, float c2, float x)
{
int c_prim = (rand() % 256); // draw any number of range [0, 255]
float w = W(x); // count helper function for given side length
return (1 - 2 * w) * c_prim + c1*w + c2 * w; // color is the result of such equation
}

// similarly for the center point
float get_middle_color(float c1, float c2, float c3, float c4, float x)
{
int c_prim = rand() % 256;
float w = Wc(x);

return (1 - 4 * w)*c_prim + w*c1 + w*c2 + w*c3 + w*c4;
}

// each time the function is invoked five new points
// are counted by which the current square is divided
// so that 4 new squares are created. Four points are
// in the middle length of the side of the square that is
// currently processed and the fifth is in the center of it
// and that brings 4 new squares. The action is repeated for
// each square in the input vector sq.
std::vector<square> divide_square(std::vector<square> sq)
{
vertex c12, c23, c34, c41, cc; // newly generated points
std::vector<square> new_squares; // newly created squares go there
float x = sq[0].x / 2; // length of new squares is half of the length of the original one
// for each square in input vector do the dividing operation
for (int i = 0; i < sq.size(); i++)
{
// initializing new vertices on the sides of old square
c12.pos[0] = sq[i].a.pos[0] + x; c12.pos[1] = sq[i].a.pos[1];
c23.pos[0] = sq[i].b.pos[0]; c23.pos[1] = sq[i].b.pos[1] + x;
c34.pos[0] = sq[i].d.pos[0] + x; c34.pos[1] = sq[i].d.pos[1];
c41.pos[0] = sq[i].a.pos[0]; c41.pos[1] = sq[i].a.pos[1] + x;
// ... and the center one:
cc.pos[0] = c12.pos[0]; cc.pos[1] = c23.pos[1];
// counting color based on above formulas
c12.c = get_color(sq[i].a.c, sq[i].b.c, x); c23.c = get_color(sq[i].b.c, sq[i].c.c, x);
c34.c = get_color(sq[i].c.c, sq[i].d.c, x); c41.c = get_color(sq[i].a.c, sq[i].d.c, x);
cc.c = get_middle_color(sq[i].a.c, sq[i].b.c, sq[i].c.c, sq[i].d.c, x);
// generating and adding four newly generated squares to the container of squares for further processing
square s1(sq[i].a, c12, cc, c41);
square s2(c12, sq[i].b, c23, cc);
square s3(cc, c23, sq[i].c, c34);
square s4(c41, cc, c34, sq[i].d);
new_squares.push_back(s1); new_squares.push_back(s2);
new_squares.push_back(s3); new_squares.push_back(s4);
}
return new_squares;
}

// dynamic two-dimensional array representing matrix for storing all
// generated squares (this array should be ordered
// in such way that each row "i" contains 256 squares
// which A vertex has Y coordinate equal to "i"
// for instance Map[3][0] should represent the first
// square which has A corner vertex coordinates like (0, 3)
square **Map = new square*[256];

// performing the dividing mechanism and filling up the
// Map matrix
void foo()
{
vertex a, b, c, d; // vertices of the entering square of size 256x256
a.pos[0] = 0.0f; a.pos[1] = 0.0f;
b.pos[0] = 256.0f; b.pos[1] = 0.0f;
c.pos[0] = 256.0f; c.pos[1] = 256.0f;
d.pos[0] = 0.0f; d.pos[1] = 256.0f;
a.c = 0.5f; b.c = 0.5f; c.c = 0.5f; d.c = 0.5f;
sq.push_back(square(a, b, c, d)); // adding it as the first the square to the container
// while generated smaller squares have the x length more than 1.0 divide them on smaller ones
while (sq[0].x > 1.0f)
{
sq = divide_square(sq);
}
int tempor = 0; // helper for iterating columns of Map matrix
float curr_y; // represent the y-coordinate of left-upper square corner (A)
for (int j = 0; j < 256; j++)
{
Map[j] = new square[256]; // new row of 256 squares is initialized
// search all squares for finding those which left-upper corner (A)
// y-coordinate is equal to the row numer
for (int i = 0; i < sq.size(); i++)
{
curr_y = sq[i].a.pos[1];
if (curr_y == j)
{
Map[j][tempor++] = sq[i];
}
}
tempor = 0; // setting to first column again
}
}

// helper global variables to set some properties
// for drawing and transforming which can be set
// by pressing some keys (they are set in key_pressed
// function)
double rot = 10.0; // rotation angle;
int rows = 1; // the variable to iterate rows of Map matrix
int columns = 10; // the variable to iterate columns of Map matrix

void key_pressed(unsigned char key, int x, int y)
{
if (key == '>')
glRotated(rot, 1.0, 1.0, 1.0);
if (key == 'z')
rows++;
if (key == 'x')
rows--;
if (key == 't')
glTranslated(-1.0, 0.0, 0.0); // translating to the left
if (key == 's')
columns += 40;
display_scene();
}
int main()
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // inicjalizacja bufora ramki: podwójne buforowanie, RGB
glutInitWindowSize(window_width, window_height);
glutCreateWindow("Terrain");

glutDisplayFunc(display_scene); // przekazanie wskaźnika do funkcji wywoływanej przez GLUT przy wyświetlaniu
glutReshapeFunc(reshape); // jw. ale przy zmianie wielkości okna
glutKeyboardFunc(key_pressed);
// invoking function to generate squares.
foo();
glutMainLoop();

return 0;
}


void display_scene(){
// setting background color
glClearColor(0.4f, 0.4f, 0.4f, 1.0);
// clearing buffer to draw new image
glClear(GL_COLOR_BUFFER_BIT);
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
// drawing quads in 3D where X and Z coordinates are just like
// the square A, B, C or D vertices X and Y coordinates and
// the Y coordinate (height) depends on the color of the vertex
// (the darker color the lower height)
glBegin(GL_QUADS);
float col = rgb_to_float(Map[i][j].a.c);
// color may be to brigth (for instance 0.0019) so some
// scalling is done
if (col < 0.1)
col *= 10;
glColor3f(col, col, col); // seting color for drawing the verticle
glVertex3f(Map[i][j].a.pos[0], col * 10, Map[i][j].a.pos[1]);
col = rgb_to_float(Map[i][j].b.c);
if (col < 0.1)
col *= 10;
glColor3f(col, col, col);
glVertex3f(Map[i][j].b.pos[0], col*10, Map[i][j].b.pos[1]);
col = rgb_to_float(Map[i][j].c.c);
if (col < 0.1)
col *= 10;
glColor3f(col, col, col);
glVertex3f(Map[i][j].c.pos[0], col*10, Map[i][j].c.pos[1]);
col = rgb_to_float(Map[i][j].d.c);
if (col < 0.1)
col *= 10;
glColor3f(col, col, col);
glVertex3f(Map[i][j].d.pos[0], col*10, Map[i][j].d.pos[1]);
glEnd();
}
}
glFlush(); // powyższe polecenia zostaną przesłąne do sterownika karty graficznej (lepsza wydajność, bo naraz podaje się wszystkie dane, a nie każdą daną po kolei, co zajmowałoby więcej czasu)
glutSwapBuffers();
}

void reshape(GLsizei width, GLsizei height){
if (height == 0) // omitting diving by zero in counting AspectRatio
height = 1;
// setting view port the same as window size
glViewport(0, 0, width, height);
// switching to projection matrix for setting proper view aspects
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat AspectRatio = (GLfloat)width / (GLfloat)height;
if (width <= height)
glOrtho(-7.5, 7.5, -7.5 / AspectRatio, 7.5 / AspectRatio, 10.0, -10.0);
else
glOrtho(-7.5*AspectRatio, 7.5*AspectRatio, -7.5, 7.5, 10.0, -10.0);
// switching to modelview matrix to enable performing transformations on
// the image such as translating, rotating etc.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

我想知道如何解决四边形断开(损坏)的问题。

最佳答案

您的“正方形”类不是计算此网格中高度的理想模型,因为每次 segmentation 时,您最终都会修改相邻正方形共享的点,也可能由父正方形共享。

至少,让您的方 block 包含对顶点的引用(或指针),并在相邻方 block 之间共享这些引用。

然后,当您修改任何顶点时,所有共享它的正方形都会自动获得更新后的坐标。

关于c++ - 在 OpenGL 中使用等 ionic 分形生成地形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33874170/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com