我想用等离子体分形生成随机地形。我在网上浏览,想找到一个解决方案,可以帮助我在我的特殊问题,但没有找到任何东西。事实上,我生成了简单的等离子体分形,它看起来像这样:
下面是分形的图片:
分形是不完美的,因为有看到的正方形,但我的老师接受。生成这种分形的算法是,给定一个输入正方形,我通过在每一个正方形边的中间插入四个点,然后在中心插入一个点,将它分割成更小的正方形,从而创建4个新的正方形。每一个新生成的顶点都有其颜色值,它是一个范围为[0,255]的浮点,该浮点使用特殊的公式进行计数。我现在有一个任务,使用这个分形生成随机地形,并且知道每个点的高度与计数的颜色值成正比。我的问题是,我试图用生成的方块角坐标来绘制四边形,但我的四边形并不相连(有些地方,两个四边形边缘的高度如此不同,以至于它们之间出现了一个间隙)。
下面是我的地形图:
下面是我生成这个地形的代码:
#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();
}
我想知道如何克服问题与断开(坏)的四线。
您的“Square”类不是计算该网格中高度的理想模型,因为每次细分时都要修改相邻方块共享的点,也可能是父方块共享的点。
至少,让您的方块包含对顶点的引用(或指针),并在相邻的方块之间共享这些引用。
然后,当你修改任何顶点时,所有共享它的方块将自动获得更新的坐标。
问题内容: 目的:使用指定的参数调用外部应用程序,然后退出脚本。 以下脚本无法正常工作: 尝试过的事情:-不分离。提前谢谢了 问题答案: 从node.js文档中: 默认情况下,父级将等待分离的子级退出。为防止父级等待给定的子级,请使用child.unref()方法,并且父级的事件循环将其引用计数中不包括该子级。 使用detached选项启动长时间运行的进程时,除非该进程提供了未连接到父级的stdi
我正在编写一个可视化洞穴的OpenGL程序,所以当我可视化地表地形时,我希望它是透明的,这样你就可以看到下面的洞穴了。我假设我可以将来自数字高程模型的数据归一化为一个网格,该网格以规则的间距对准x/z轴,并将每个网格单元格渲染为两个三角形。使用对齐的网格,我可以避免在应用画家的算法时进行排序的成本(以确保适当的透明度效果);相反,我可以逐行呈现单元格,从最远的行和每行最远的单元格开始。 这一切都很
我想做一个简单的2D地形,只有几个颠簸和高度变化: 我想过只是用随机数来描述某个顶点的高度,但我看不出我怎么能从这个做一个网格。我正在寻找一种方法来找到地形的顶点和索引缓冲区。 我如何做到这一点?
问题内容: 我正在使用ionic框架为android平台生成apk。 运行后,将生成android-debug.apk。如何生成更小,更快的非调试apk? 问题答案: 这是我的android发布shell脚本 IFY
我使用离子框架生成apkAndroid平台。 运行后,将进行Android调试。生成apk。如何生成更小更快的非调试apk?