void DeferredContainer::makeTarget() {
    if(Window::getInstance()->getSize() == gBuffer.getSize()) return;
    vec2ui size = Window::getInstance()->getSize();
    GBDepth = Texture2D(size, TextureFormat::DEPTH_COMPONENT32F);
    GBDepth.setFilter(GL_NEAREST, GL_NEAREST);
    GBColor0 = Texture2D(size, TextureFormat::RGBA16F);
    GBColor0.setFilter(GL_NEAREST, GL_NEAREST);
    GBColor1 = Texture2D(size, TextureFormat::RGBA16F);
    GBColor1.setFilter(GL_NEAREST, GL_NEAREST);
    gBuffer = RenderTarget(size.x, size.y);
    gBuffer.setTexture(RenderTargetBase::DEPTH, &GBDepth); //Z-BUFFER
    gBuffer.setTexture(RenderTargetBase::COLOR0, &GBColor0); //COLOR
    gBuffer.setTexture(RenderTargetBase::COLOR1, &GBColor1); //NORMAL, BRIGHTNESS, SPECULAR FACTOR
    if(sunTarget.getSize() == vec2ui(0)) { //invalid (this is the first makeTarget() )
        SDepth = Texture2DArray(vec3ui(4096,4096, NUM_SUN_CASCADES), TextureFormat::DEPTH_COMPONENT32F);
        SDepth.setFilter(GL_LINEAR, GL_LINEAR);
        SDepth.setComparison(GL_GREATER);
        sunTarget = RenderTargetLayered(4096, 4096, NUM_SUN_CASCADES);
        sunTarget.setTexture(RenderTargetBase::DEPTH, &SDepth); //Z-BUFFER

        SDepthTrans = Texture2DArray(vec3ui(4096,4096, NUM_SUN_CASCADES), TextureFormat::DEPTH_COMPONENT32F);
        SDepthTrans.setFilter(GL_LINEAR, GL_LINEAR);
        SDepthTrans.setComparison(GL_GREATER);
        sunTargetTrans = RenderTargetLayered(4096, 4096, NUM_SUN_CASCADES);
        sunTargetTrans.setTexture(RenderTargetBase::DEPTH, &SDepthTrans); //Z-BUFFER
    }
}
Beispiel #2
0
    vec3ui Material::getParam(const char *name, vec3ui defaultVal) 
    {
      ParamMap::iterator it = params.find(name);
      if (it != params.end()) {
        assert( it->second->type == Param::UINT_3 && "Param type mismatch" );
        return vec3ui(it->second->ui[0], it->second->ui[1], it->second->ui[2]);
      }

      return defaultVal;
    }
Beispiel #3
0
GLWindow::GLWindow(QWidget *parent) :
	QGLWidget(parent)
{
	
	// настраиваем формат Qt OpenGL
	gl_format.setDirectRendering(true);
	gl_format.setDoubleBuffer(true);
	gl_format.setSampleBuffers(true);
	
	// ...и устанавливаем
	setFormat(gl_format);

	// устанавливаем параметры по-умолчанию
    is_multithreading = false;
	threads_num = 1;
    isolevel = 30.0f; isolevel_begin = 0.0f; isolevel_end = 30.0f;
    isolevel_step = 0.01f; isolevel_is_animate = 0;
    camera_step = 0.2f; camera_move_speed = 15.0f; camera_fov = 16.0f;

    material_front_color = vec3f(0.5f, 0.5f, 0.5f);
	material_back_color = vec3f(0.5f, 0.0f, 0.0f);
    light_color = vec3f(1.0f, 1.0f, 1.0f);
    light_spec_color = vec3f(1.0f, 1.0f, 1.0f);
    material_shininess = 30.0f; coef_gamma = 2.2f; coef_ambient = 0.5f;
    coef_diffuse = 1.0f; coef_specular = 1.0f;

    volume_size = vec3ui(128, 128, 128); grid_size = vec3ui(40, 40, 40);

    light_angle = 0.0f; light_rot_step = 0.01f;
    light_is_animate = 0;
	
	// устанавливаем фокус для окна OpenGL
	setFocusPolicy(Qt::StrongFocus);
	
	// запкскаем основной таймер
	timer_id = startTimer(0);
}
void TestLinAlg()
{
    // Instantiate templates, check sizes, make sure operators compile etc.

    static_assert(sizeof(Vec2f)     == 8  , "Vec2f size test failed"    );
    static_assert(sizeof(Vec3f)     == 12 , "Vec3f size test failed"    );
    static_assert(sizeof(Vec4f)     == 16 , "Vec4f size test failed"    );
    static_assert(sizeof(Vec2d)     == 16 , "Vec2d size test failed"    );
    static_assert(sizeof(Vec3d)     == 24 , "Vec3d size test failed"    );
    static_assert(sizeof(Vec4d)     == 32 , "Vec4d size test failed"    );
    static_assert(sizeof(Vec2i)     == 8  , "Vec2i size test failed"    );
    static_assert(sizeof(Vec3i)     == 12 , "Vec3i size test failed"    );
    static_assert(sizeof(Vec4i)     == 16 , "Vec4i size test failed"    );
    static_assert(sizeof(Vec2ui)    == 8  , "Vec2ui size test failed"   );
    static_assert(sizeof(Vec3ui)    == 12 , "Vec3ui size test failed"   );
    static_assert(sizeof(Vec4ui)    == 16 , "Vec4ui size test failed"   );
    static_assert(sizeof(Matrix44f) == 64 , "Matrix44f size test failed");
    static_assert(sizeof(Matrix44d) == 128, "Matrix44d size test failed");

    Vec2f vec2f(0.0f, 0.0f);
    Vec3f vec3f(0.0f, 0.0f, 0.0f);
    Vec4f vec4f(0.0f, 0.0f, 0.0f, 0.0f);
    Vec2d vec2d(0.0, 0.0);
    Vec3d vec3d(0.0, 0.0, 0.0);
    Vec4d vec4d(0.0, 0.0, 0.0, 0.0);
    Vec2i vec2i(-1, -1);
    Vec3i vec3i(-1, -1, -1);
    Vec4i vec4i(-1, -1, -1, -1);
    Vec2ui vec2ui(0, 0);
    Vec3ui vec3ui(0, 0, 0);
    Vec4ui vec4ui(0, 0, 0, 0);
    float f = 0.0f;
    bool b = false;

    b = (vec3f == vec3f);
    b = (vec3f != vec3f);
    vec3f = Vec3f(1.0f) + Vec3f(2.0f);
    vec3f = Vec3f(1.0f) - Vec3f(2.0f);
    vec3f = Vec3f(1.0f) * Vec3f(2.0f);
    vec3f = Vec3f(1.0f) / Vec3f(2.0f);
    vec3f = Vec3f(1.0f) * f;
    vec3f = f * Vec3f(1.0f);
    vec3f = Vec3f(1.0f) / f;
    vec3f = -Vec3f(1.0f);
    vec3f += Vec3f(1.0f);
    vec3f -= Vec3f(1.0f);
    vec3f *= Vec3f(1.0f);
    vec3f /= Vec3f(1.0f);
    vec3f *= f;
    vec3f /= f;
    f = vec3f[0];
    vec3f[0] = f;
    f = Length(vec3f);
    f = LengthSquared(vec3f);
    vec3f = Normalize(vec3f);
    f = Dot(Vec3f(1.0f), Vec3f(2.0f));
    vec3f = Vec3f(1.0f) ^ Vec3f(2.0f);

    Matrix44f matf;
    matf.Identity();
    Matrix44d matd;
    matf.RotationX(1);
    matf.RotationY(1);
    matf.RotationZ(1);
    matf.Scaling(1);
    b = matf == matf;
    matf = matf * matf;
    matf.BuildLookAtMatrix(Vec3f(0.0f, 10.0f, 10.0f), Vec3f(0.0f));
    matf.BuildProjection(90.0f, 4.0f / 3.0f, 1.0f, 1000.0f);
    Vec3f out;
    matf.Transf3x3(vec3f, out);
    matf.Transf4x4(vec3f, out);
    matf.Transpose3x3();
    matf.Transpose4x4();
    matf.Invert();
}
Beispiel #5
0
void render_set_volume_size(vector3ui volume_size_v, int rebuild)
{
	volume_size = vec3ui_add_c(volume_size_v, 1);
	volume_step = vec3f_div(vec3f(1.0f, 1.0f, 1.0f), vec3ui_to_vec3f(volume_size));
	
	if(rebuild) {

		new_volume = (float*) malloc(sizeof(float) * volume_size.x*volume_size.y*volume_size.z);
		IF_FAILED(new_volume != NULL);

		is_stop_building = 0;

		if(parser_is_stopped())
			parser_resume();

		// проверяем количество потоков и решаем использовать ли многопоточность
		if(num_threads >= 2) {

			// устанавливаем кол-во потоков
			omp_set_num_threads(num_threads);

			int *stop_ptr = &is_stop_building;

			// запускаем паралельно данный участок кода
			#pragma omp parallel firstprivate(volume_size) shared(new_volume, str_function, stop_ptr)
			{
				int i = omp_get_thread_num();

				parser_t tparser;
				parser_create(&tparser);
				parser_clean(&tparser);

				// вычисляем интервал вычислений для данного потока
				vector3ui begin = vec3ui(0, 0, volume_size.z * ((float) (i) / (float) omp_get_num_threads()));
				vector3ui end = vec3ui(volume_size.x, volume_size.y, volume_size.z * ((float) (i+1) / (float) omp_get_num_threads()));

				float_var_value_t float_vars[] =
				{
					{1, 0.0f}, // d
					{2, 0.0f}, // x
					{3, 0.0f}, // y
					{4, 0.0f}, // z
					{0, 0.0f}
				};

				// проходимся по соотвествующему участку массива
				for(unsigned k = begin.z; k < end.z; k++) {
					for(unsigned j = begin.y; j < end.y; j++) {
						for(unsigned i = begin.x; i < end.x; i++) {

							if(*stop_ptr)
								goto exit_loop;

							float_vars[0].value = 0.0f; float_vars[1].value = i;
							float_vars[2].value = j; float_vars[3].value = k;

							if(parser_parse_text(&tparser, str_function, float_vars) == 0) {
								new_volume[i + j*volume_size.x + k*volume_size.x*volume_size.y] = float_vars[0].value;
							}
						}
					}
				}

				exit_loop:

				parser_clean(&tparser);
			}

		} else {
			// проходимся по всему массиву и устанавливаем соотвествующее функции значение
			for(unsigned k = 0; k < volume_size.z; k++) {
				for(unsigned j = 0; j < volume_size.y; j++) {
					for(unsigned i = 0; i < volume_size.x; i++) {

						if(is_stop_building)
							goto exit_loop2;

						new_volume[i + j*volume_size.x + k*volume_size.x*volume_size.y] = volume_func(vec3f(i, j, k));
					}
				}
			}

			exit_loop2: ; // ....

		}


		if(!is_stop_building) {

			is_swap_volumes = 1;
		} else {
			free(new_volume);
			new_volume = NULL;

			is_swap_volumes = 0;
		}

	}

}
Beispiel #6
0
int render_init(void)
{
	IF_FAILED0(!init);

	if(!init_opengl) {
		ERROR_MSG("OpenGL not initialised\n");
		return 0;
	}

	log_init();
	
	TRACE_MSG("init base render system\n");
	
	TRACE_MSG("init noise\n");
	noise_init();
	
	glViewport(0, 0, window_width, window_height);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glEnable(GL_DEPTH_TEST);
	glClearDepth(1.0f);
	
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_CLAMP);
	
	DEBUG_MSG("OpenGL version: %s\n", glGetString(GL_VERSION));
	DEBUG_MSG("GLSL version: %s\n", (char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
	
	// настраиваем основную камеру
	TRACE_MSG("init main camera\n");
	camera_init(&camera, vec3f(0.0f, 0.0f, 0.5f), vec3f(0.0f, 1.0f, 0.0f), vec3f(0.0f, 0.0f, -1.0f));
	camera_set_limit(&camera, -95.0f, 95.0f, -360.0f, 360.0f);
	camera_set_fov(&camera, camera_fov);
	camera_set_move_velocity(&camera, camera_move_speed);
	camera_set_rotate_velocity(&camera, camera_rotate_speed);
	camera_set_aspect(&camera, (float) window_width / (float) window_height);
	camera_set_zplanes(&camera, 0.001f, 1000.0f);
	camera_update(&camera, 0.0);
	
	isolevel = 30.0f; 
	isolevel_animate = 0;
	
	// устанавливаем функцию по-умолчанию
	parser_create(&parser);
	const char *default_func = "d = y;";
	str_function = (char*) malloc(sizeof(char) * (strlen(default_func) + 1));
	strcpy(str_function, default_func);
	
	// настраиваем и создаем скалярное поле
	render_set_volume_size(vec3ui(128, 128, 128), 1);
	render_set_grid_size(vec3ui(64, 64, 64));
	render_update_volume_tex();
	
	CHECK_GL_ERRORS();
	
	// инициализируем шейдер
	if(!init_shader())
		return 0;
	
	// инициализируем буферы с данными
	init_buffers();
	
	// устанавливаем параметры по-умолчанию
	new_light_position = light_position = vec3f(1.0f, 1.0f, 1.0f);
	rot_axis = vec3f(0.0f, 1.0f, 0.0f);
	num_threads = 1;
	rot_angle = 0.0f;
	light_animate = 0;
	light_rot_angle = 0.0f;
	mat4(rotmat, 1.0f);
	mat4(modelmat, 1.0f);
	material_front_color = vec3f(0.5f, 0.5f, 0.5f);
	material_back_color = vec3f(0.5f, 0.0f, 0.0f);
	light_color = vec3f(1.0f, 1.0f, 1.0f);
	light_spec_color = vec3f(1.0f, 1.0f, 1.0f);
	
	input_set_wheel_limits(20, 150);
	
	init = 1;
	
	// полигонизируем ск. п.
	render_update_mc();
	
	// обновляем рендер
	render_update(0.0f);
	
	return 1;
}
Beispiel #7
0
	TriMesh<FloatType>::TriMesh( const MeshData<FloatType>& meshData )
	{

		m_Vertices.resize(meshData.m_Vertices.size());

		m_bHasNormals = meshData.m_Normals.size() > 0;
		m_bHasColors = meshData.m_Colors.size() > 0;
		m_bHasTexCoords = meshData.m_TextureCoords.size() > 0;

		for (size_t i = 0; i < m_Vertices.size(); i++) {
			m_Vertices[i].position = meshData.m_Vertices[i];
		}

		for (unsigned int i = 0; i < meshData.m_FaceIndicesVertices.size(); i++) {
			if (meshData.m_FaceIndicesVertices[i].size() == 3) {
				//we need to split vertices if the same vertex has different texcoords and/or normals
				bool bFaceHasNormals	= m_bHasNormals && meshData.getFaceIndicesNormals()[i].size() > 0;
				bool bFaceHasTexCoords	= m_bHasTexCoords && meshData.getFaceIndicesTexCoords()[i].size() > 0;
				bool bFaceHasColors		= m_bHasColors && meshData.getFaceIndicesColors()[i].size() > 0;

				if (bFaceHasNormals || bFaceHasTexCoords || bFaceHasColors) {
					vec3ui coords = vec3ui(0,0,0);
					for (unsigned int j = 0; j < 3; j++) {
						bool vertexSplit = false;
						if (bFaceHasNormals) { //split if normal is different than the one found before
							const point3d<FloatType>& n = meshData.m_Normals[meshData.getFaceIndicesNormals()[i][j]];
							if (m_Vertices[meshData.getFaceIndicesVertices()[i][j]].normal != point3d<FloatType>::origin && 
								m_Vertices[meshData.getFaceIndicesVertices()[i][j]].normal != n)	vertexSplit = true;
						}
						if (bFaceHasTexCoords) { //split if texcoord is different than the one found before
							const point2d<FloatType>& t = meshData.m_TextureCoords[meshData.getFaceIndicesTexCoords()[i][j]];
							if (m_Vertices[meshData.getFaceIndicesVertices()[i][j]].texCoord != point2d<FloatType>::origin && 
								m_Vertices[meshData.getFaceIndicesVertices()[i][j]].texCoord != t) vertexSplit = true;
						}
						if (bFaceHasColors) { //split if texcoord is different than the one found before
							const point4d<FloatType>& c = meshData.m_Colors[meshData.getFaceIndicesColors()[i][j]];
							if (m_Vertices[meshData.getFaceIndicesVertices()[i][j]].color != point4d<FloatType>::origin && 
								m_Vertices[meshData.getFaceIndicesVertices()[i][j]].color != c) vertexSplit = true;
						}

						if (vertexSplit) {
							MLIB_WARNING("vertex split untested");
							Vertex<FloatType> v = m_Vertices[meshData.getFaceIndicesVertices()[i][j]];
							if (bFaceHasNormals)		v.normal = meshData.m_Normals[meshData.getFaceIndicesNormals()[i][j]];
							if (bFaceHasTexCoords)	v.texCoord = meshData.m_TextureCoords[meshData.getFaceIndicesTexCoords()[i][j]];
							if (bFaceHasColors)		v.color = meshData.m_Colors[meshData.getFaceIndicesColors()[i][j]];
							m_Vertices.push_back(v);
							coords[j] = (unsigned int)m_Vertices.size() - 1;
						} else {
							if (bFaceHasNormals)		m_Vertices[meshData.getFaceIndicesVertices()[i][j]].normal = meshData.m_Normals[meshData.getFaceIndicesNormals()[i][j]];
							if (bFaceHasTexCoords)	m_Vertices[meshData.getFaceIndicesVertices()[i][j]].texCoord = meshData.m_TextureCoords[meshData.getFaceIndicesTexCoords()[i][j]];
							if (bFaceHasColors)		m_Vertices[meshData.getFaceIndicesVertices()[i][j]].color = meshData.m_Colors[meshData.getFaceIndicesColors()[i][j]];
							coords[j] = meshData.getFaceIndicesVertices()[i][j];
						}
					}
					m_Indices.push_back(coords);

					//m_Indices.push_back(vec3ui(meshData.m_FaceIndicesVertices[i][0], meshData.m_FaceIndicesVertices[i][1], meshData.m_FaceIndicesVertices[i][2]));
					//if (hasNormals) {
					//	//we are ignoring the fact that sometimes there might be vertex split required (if a vertex has two different normals)
					//	m_Vertices[m_Indices[i][0]].normal = meshData.m_Normals[meshData.m_FaceIndicesNormals[i][0]];
					//	m_Vertices[m_Indices[i][1]].normal = meshData.m_Normals[meshData.m_FaceIndicesNormals[i][1]];
					//	m_Vertices[m_Indices[i][2]].normal = meshData.m_Normals[meshData.m_FaceIndicesNormals[i][2]];
					//}
					//if (hasTexCoords) {
					//	//we are ignoring the fact that sometimes there might be vertex split required (if a vertex has two different normals)
					//	m_Vertices[m_Indices[i][0]].texCoord = meshData.m_TextureCoords[meshData.m_FaceIndicesTextureCoords[i][0]];
					//	m_Vertices[m_Indices[i][1]].texCoord = meshData.m_TextureCoords[meshData.m_FaceIndicesTextureCoords[i][1]];
					//	m_Vertices[m_Indices[i][2]].texCoord = meshData.m_TextureCoords[meshData.m_FaceIndicesTextureCoords[i][2]];
					//}
				} else {
					m_Indices.push_back(vec3ui(meshData.m_FaceIndicesVertices[i][0], meshData.m_FaceIndicesVertices[i][1], meshData.m_FaceIndicesVertices[i][2]));
				}
			} else {
				MLIB_WARNING("non triangle face found - ignoring it");
			}
		}
	}
Beispiel #8
0
    TriMesh<FloatType> TriMesh<FloatType>::flatLoopSubdivision(float minEdgeLength) const
    {
        struct Edge
        {
            Edge(UINT32 _v0, UINT32 _v1)
            {
                v0 = std::min(_v0, _v1);
                v1 = std::max(_v0, _v1);
            }

            union
            {
                struct {
                    UINT32 v0, v1;
                };
                UINT64 val;
            };
        };

        struct edgeCompare
        {
            bool operator() (const Edge &a, const Edge &b)
            {
                return a.val < b.val;
            }
        };
        
        map<Edge, UINT, edgeCompare> edgeToNewVertexMap;

        TriMesh<FloatType> result;
        
        result.m_Vertices = m_Vertices;
        result.m_Indices.reserve(m_Indices.size() * 4);

        for (const vec3ui &tri : m_Indices)
        {
            /*bool subdivide = true;
            for (UINT eIndex = 0; eIndex < 3; eIndex++)
            {
                const vec3f &v0 = m_Vertices[tri[eIndex]].position;
                const vec3f &v1 = m_Vertices[tri[(eIndex + 1) % 3]].position;
                float edgeLength = vec3f::dist(v0, v1);
                if (edgeLength < minEdgeLength)
                    subdivide = false;
            }*/
            bool subdivide = math::triangleArea(m_Vertices[tri[0]].position, m_Vertices[tri[1]].position, m_Vertices[tri[2]].position) >= (minEdgeLength * minEdgeLength);

            if (subdivide)
            {
                UINT edgeMidpoints[3];

                for (UINT eIndex = 0; eIndex < 3; eIndex++)
                {
                    const UINT v0 = tri[eIndex];
                    const UINT v1 = tri[(eIndex + 1) % 3];
                    Edge e = Edge(v0, v1);
                    if (edgeToNewVertexMap.count(e) == 0)
                    {
                        edgeToNewVertexMap[e] = (UINT)result.m_Vertices.size();
                        result.m_Vertices.push_back((m_Vertices[v0] + m_Vertices[v1]) * (FloatType)0.5);
                    }

                    edgeMidpoints[eIndex] = edgeToNewVertexMap[e];
                }

                result.m_Indices.push_back(vec3ui(tri[0], edgeMidpoints[0], edgeMidpoints[2]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[0], tri[1], edgeMidpoints[1]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[2], edgeMidpoints[1], tri[2]));
                result.m_Indices.push_back(vec3ui(edgeMidpoints[2], edgeMidpoints[0], edgeMidpoints[1]));
            }
            else
            {
                result.m_Indices.push_back(tri);
            }
        }

        return result;
    }
Beispiel #9
0
void WorldGenerator::generateChunk(Chunk *chunk) {
	vec3i64 cc = chunk->getCC();
	const ElevationChunk elevation = elevationGenerator.getChunk(vec2i64(cc[0], cc[1]));
	bool underground = cc[2] * Chunk::WIDTH <= std::ceil(elevation.max);
	if (underground) {
		tunnelSwitchPerlin.noise3(
			cc.cast<double>() * Chunk::WIDTH / wp.tunnelSwitchScale / wp.overall_scale,
			vec3d(1 / wp.tunnelSwitchScale / wp.overall_scale),
			vec3ui(Chunk::WIDTH, Chunk::WIDTH, Chunk::WIDTH + 9),
			wp.tunnelSwitchOctaves, wp.tunnelSwitchAmplGain, wp.tunnelSwitchFreqGain,
			tunnelSwitchBuffer
		);
		cavenessPerlin.noise3(
			cc.cast<double>() * Chunk::WIDTH / wp.cavenessScale / wp.overall_scale,
			vec3d(1 / wp.cavenessScale / wp.overall_scale),
			vec3ui(Chunk::WIDTH, Chunk::WIDTH, Chunk::WIDTH + 9),
			wp.cavenessOctaves, wp.cavenessAmplGain, wp.cavenessFreqGain,
			cavenessBuffer
		);
	}

	for (uint iccx = 0; iccx < Chunk::WIDTH; iccx++)
	for (uint iccy = 0; iccy < Chunk::WIDTH; iccy++) {
		int64 bcx = cc[0] * Chunk::WIDTH + iccx;
		int64 bcy = cc[1] * Chunk::WIDTH + iccy;
			
		double h = elevation.heights[iccy * Chunk::WIDTH + iccx];
		double base_vegetation = 0;
		double base_temperature = 0;

		bool solid = false;
		int realDepth = 0;
		for (int iccz = Chunk::WIDTH + 8; iccz >= 0; iccz--) {
			int64 bcz = iccz + cc[2] * Chunk::WIDTH;
			vec3d dbc = vec3i64(bcx, bcy, bcz).cast<double>();
			
			const double depth = h - bcz;

			if (depth < 0) {
				solid = false;
			} else if (depth > (h * wp.surfaceRelDepth)) {
				solid = true;
			} else {
				const double xScale = wp.surfaceThresholdXScale;
				double funPos = 1.0 - depth / (h * wp.surfaceRelDepth) * 2;
				double threshold = funPos * (xScale * xScale + funPos * funPos) / (xScale * xScale + 1) * 2.0;
				double v = surfacePerlin.noise3(
					dbc / wp.surfaceScale,
					wp.surfaceOctaves, wp.surfaceAmplGain, wp.surfaceFreqGain
				);
				if (v > threshold)
					solid = true;
				else
					solid = false;
			}

			if (solid)
				realDepth++;
			else
				realDepth = 0;

			uint8 block;
			if (iccz < (int) Chunk::WIDTH) {
				if (solid) {
					if (base_temperature > wp.desert_threshold && realDepth < 5)
						block = 4; // sand
					else if (base_vegetation > wp.grasland_threshold && realDepth == 1)
						block = 2; // gras
					else if (realDepth >= 5)
						block = 3; // dirt
					else
						block = 1; // stone
				} else {
					if (realDepth <= 0 && bcz <= 0)
						block = 62; // water
					else
						block = 0; // air
				}

				// TODO cave rooms
				// TODO height dependent
				// caves
				if (block != 0) {
					if (!underground)
						LOG_ERROR(logger) << "Trying to generate caves, but not underground";
					uint index = ((iccz * Chunk::WIDTH) + iccy) * Chunk::WIDTH + iccx;
					double depthValue1 = wp.cavenessDepthGainFac1 * (1 - 1 / (depth / wp.cavenessDepthGain1 + 1));
					double depthValue2 = wp.cavenessDepthGainFac2 * (1 - 1 / (depth / wp.cavenessDepthGain2 + 1));
					double caveness = (cavenessBuffer[index] + 0.5) * (depthValue1 + depthValue2);
					double tunnelSwitch = tunnelSwitchBuffer[index];
					double overLap = wp.tunnelSwitchOverlap;
					double tunnelValue1 = 0;
					double tunnelValue2 = 0;
					vec3d tunnelCoords(dbc / wp.tunnelScale);
					if (tunnelSwitch > -overLap) {
						const double v1 = std::abs(tunnelPerlin1a.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						const double v2 = std::abs(tunnelPerlin2a.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						const double v3 = std::abs(tunnelPerlin3a.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						double v12 = 1 / ((v1 * v1 + 1) * (v2 * v2 + 1) - 1);
						double v23 = 1 / ((v2 * v2 + 1) * (v3 * v3 + 1) - 1);
						double ramp = 1;
						if (tunnelSwitch < 0)
							ramp = (overLap + tunnelSwitch) / overLap;
						tunnelValue1 = (v12 + v23) * ramp;
					}
					if (block != 0 && tunnelSwitch < overLap) {
						const double v1 = std::abs(tunnelPerlin1b.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						const double v2 = std::abs(tunnelPerlin2b.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						const double v3 = std::abs(tunnelPerlin3b.noise3(
								tunnelCoords, wp.tunnelOctaves, wp.tunnelAmplGain, wp.tunnelFreqGain));
						double v12 = 1 / ((v1 * v1 + 1) * (v2 * v2 + 1) - 1);
						double v23 = 1 / ((v2 * v2 + 1) * (v3 * v3 + 1) - 1);
						double ramp = 1;
						if (tunnelSwitch > 0)
							ramp = (overLap - tunnelSwitch) / overLap;
						tunnelValue2 = (v12 + v23) * ramp;
					}
					if (caveness * caveness * (wp.caveRoomValue + tunnelValue1 + tunnelValue2) > wp.caveThreshold) {
						block = 0;
					}
				}

				vec3ui8 icc(iccx, iccy, iccz);
				chunk->initBlock(icc, block);
			}
		}
	}

	chunk->finishInitialization();
}