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 } }
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; }
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(); }
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; } } }
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; }
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"); } } }
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; }
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(); }