void CaveV6::makeTunnel(bool dirswitch) { if (dirswitch && !large_cave) { main_direction = v3f( ((float)(ps->next() % 20) - (float)10) / 10, ((float)(ps->next() % 20) - (float)10) / 30, ((float)(ps->next() % 20) - (float)10) / 10 ); main_direction *= (float)ps->range(0, 10) / 10; } // Randomize size s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; rs = ps->range(min_d, max_d); s16 rs_part_max_length_rs = rs * part_max_length_rs; v3s16 maxlen; if (large_cave) { maxlen = v3s16( rs_part_max_length_rs, rs_part_max_length_rs / 2, rs_part_max_length_rs ); } else { maxlen = v3s16( rs_part_max_length_rs, ps->range(1, rs_part_max_length_rs), rs_part_max_length_rs ); } v3f vec( (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2, (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 ); // Jump downward sometimes if (!large_cave && ps->range(0, 12) == 0) { vec = v3f( (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 ); } // Do not make caves that are entirely above ground, to fix // shadow bugs caused by overgenerated large caves. // It is only necessary to check the startpoint and endpoint. v3s16 orpi(orp.X, orp.Y, orp.Z); v3s16 veci(vec.X, vec.Y, vec.Z); s16 h1; s16 h2; v3s16 p1 = orpi + veci + of + rs / 2; if (p1.Z >= node_min.Z && p1.Z <= node_max.Z && p1.X >= node_min.X && p1.X <= node_max.X) { u32 index1 = (p1.Z - node_min.Z) * mg->ystride + (p1.X - node_min.X); h1 = mg->heightmap[index1]; } else { h1 = water_level; // If not in heightmap } v3s16 p2 = orpi + of + rs / 2; if (p2.Z >= node_min.Z && p2.Z <= node_max.Z && p2.X >= node_min.X && p2.X <= node_max.X) { u32 index2 = (p2.Z - node_min.Z) * mg->ystride + (p2.X - node_min.X); h2 = mg->heightmap[index2]; } else { h2 = water_level; } // If startpoint and endpoint are above ground, // disable placing of nodes in carveRoute while // still running all pseudorandom calls to ensure // caves consistent with existing worlds. bool tunnel_above_ground = p1.Y > h1 && p2.Y > h2; vec += main_direction; v3f rp = orp + vec; if (rp.X < 0) rp.X = 0; else if (rp.X >= ar.X) rp.X = ar.X - 1; if (rp.Y < route_y_min) rp.Y = route_y_min; else if (rp.Y >= route_y_max) rp.Y = route_y_max - 1; if (rp.Z < 0) rp.Z = 0; else if (rp.Z >= ar.Z) rp.Z = ar.Z - 1; vec = rp - orp; float veclen = vec.getLength(); // As odd as it sounds, veclen is *exactly* 0.0 sometimes, causing a FPE if (veclen < 0.05) veclen = 1.0; // Every second section is rough bool randomize_xz = (ps2->range(1, 2) == 1); // Carve routes for (float f = 0; f < 1.0; f += 1.0 / veclen) carveRoute(vec, f, randomize_xz, tunnel_above_ground); orp = rp; }
void CaveFractal::makeTunnel(bool dirswitch) { // Randomize size s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; rs = ps->range(min_d, max_d); s16 rs_part_max_length_rs = rs * part_max_length_rs; v3s16 maxlen; maxlen = v3s16( rs_part_max_length_rs, rs_part_max_length_rs / 2, rs_part_max_length_rs ); v3f vec; // Jump downward sometimes vec = v3f( (float)(ps->next() % maxlen.X) - (float)maxlen.X / 2, (float)(ps->next() % maxlen.Y) - (float)maxlen.Y / 2, (float)(ps->next() % maxlen.Z) - (float)maxlen.Z / 2 ); // Do not make caves that are above ground. // It is only necessary to check the startpoint and endpoint. v3s16 orpi(orp.X, orp.Y, orp.Z); v3s16 veci(vec.X, vec.Y, vec.Z); v3s16 p; p = orpi + veci + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); s16 h = mg->heightmap[index]; if (h < p.Y) return; } else if (p.Y > water_level) { return; // If it's not in our heightmap, use a simple heuristic } p = orpi + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); s16 h = mg->heightmap[index]; if (h < p.Y) return; } else if (p.Y > water_level) { return; } vec += main_direction; v3f rp = orp + vec; if (rp.X < 0) rp.X = 0; else if (rp.X >= ar.X) rp.X = ar.X - 1; if (rp.Y < route_y_min) rp.Y = route_y_min; else if (rp.Y >= route_y_max) rp.Y = route_y_max - 1; if (rp.Z < 0) rp.Z = 0; else if (rp.Z >= ar.Z) rp.Z = ar.Z - 1; vec = rp - orp; float veclen = vec.getLength(); if (veclen < 0.05) veclen = 1.0; // Every second section is rough bool randomize_xz = (ps->range(1, 2) == 1); // Carve routes for (float f = 0; f < 1.0; f += 1.0 / veclen) carveRoute(vec, f, randomize_xz); orp = rp; }
void CaveV7::makeTunnel(bool dirswitch) { if (dirswitch && !large_cave) { main_direction = v3f( ((float)(ps->next() % 20) - (float)10) / 10, ((float)(ps->next() % 20) - (float)10) / 30, ((float)(ps->next() % 20) - (float)10) / 10 ); main_direction *= (float)ps->range(0, 10) / 10; } // Randomize size s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; rs = ps->range(min_d, max_d); v3s16 maxlen; if (large_cave) { maxlen = v3s16( rs * part_max_length_rs, rs * part_max_length_rs / 2, rs * part_max_length_rs ); } else { maxlen = v3s16( rs * part_max_length_rs, ps->range(1, rs * part_max_length_rs), rs * part_max_length_rs ); } v3f vec; // Jump downward sometimes if (!large_cave && ps->range(0, 12) == 0) { vec = v3f( (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, (float)(ps->next() % (maxlen.Y * 2)) - (float)maxlen.Y, (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 ); } else { vec = v3f( (float)(ps->next() % (maxlen.X * 1)) - (float)maxlen.X / 2, (float)(ps->next() % (maxlen.Y * 1)) - (float)maxlen.Y / 2, (float)(ps->next() % (maxlen.Z * 1)) - (float)maxlen.Z / 2 ); } // Do not make large caves that are above ground. // It is only necessary to check the startpoint and endpoint. if (large_cave) { v3s16 orpi(orp.X, orp.Y, orp.Z); v3s16 veci(vec.X, vec.Y, vec.Z); v3s16 p; p = orpi + veci + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); s16 h = mg->ridge_heightmap[index]; if (h < p.Y) return; } else if (p.Y > water_level) { return; // If it's not in our heightmap, use a simple heuristic } p = orpi + of + rs / 2; if (p.Z >= node_min.Z && p.Z <= node_max.Z && p.X >= node_min.X && p.X <= node_max.X) { u32 index = (p.Z - node_min.Z) * mg->ystride + (p.X - node_min.X); s16 h = mg->ridge_heightmap[index]; if (h < p.Y) return; } else if (p.Y > water_level) { return; } } vec += main_direction; v3f rp = orp + vec; if (rp.X < 0) rp.X = 0; else if (rp.X >= ar.X) rp.X = ar.X - 1; if (rp.Y < route_y_min) rp.Y = route_y_min; else if (rp.Y >= route_y_max) rp.Y = route_y_max - 1; if (rp.Z < 0) rp.Z = 0; else if (rp.Z >= ar.Z) rp.Z = ar.Z - 1; vec = rp - orp; float veclen = vec.getLength(); if (veclen < 0.05) veclen = 1.0; // Every second section is rough bool randomize_xz = (ps->range(1, 2) == 1); // Make a ravine every once in a while if it's long enough float xylen = vec.X * vec.X + vec.Z * vec.Z; bool is_ravine = (xylen > 500.0) && !large_cave && (ps->range(1, 8) == 1); // Carve routes for (float f = 0; f < 1.0; f += 1.0 / veclen) carveRoute(vec, f, randomize_xz, is_ravine); orp = rp; }