geo FragmentShader(VertexOut vertex, Field <geo> Geo) { geo here = Geo[Here], right = Geo[RightOne], up = Geo[UpOne], left = Geo[LeftOne], down = Geo[DownOne], up_right = Geo[UpRight], up_left = Geo[UpLeft], down_right = Geo[DownRight], down_left = Geo[DownLeft]; if (!IsValid(here.dir)) { return(here); } vec2 id_here = here.geo_id; if (right.geo_id != id_here || left.geo_id != id_here || up.geo_id != id_here || down.geo_id != id_here || up_right.geo_id != id_here || up_left.geo_id != id_here || down_right.geo_id != id_here || down_left.geo_id != id_here) { //here.dist = 1; return(geo.Nothing); } return(here); }
color FragmentShader(VertexOut vertex, Field <geo> Geo, PointSampler Texture) { color output = color.TransparentBlack; geo here = Geo[Here]; vec2 subcell_pos = get_subcell_pos(vertex, Geo.Size); if (here.dir > _0) { // Draw arrow //output += DrawDebugInfoTile(here.dir, 0, subcell_pos, Texture); // Draw bad cell info //if (here.bad == _true) output.r = 1; // Draw guid coloring vec2 guid = fmod(here.geo_id * 1293.4184145f, 1.0f); output.r += guid.x; output.g += guid.y; output.a = 1f; output.rgb *= output.a; // Draw arrow over output *= DrawDebugArrow(here.dir, subcell_pos, Texture); } return(output); }
geo FragmentShader(VertexOut vertex, Field <geo> Geo) { geo geo_here = Geo[Here]; geo_here.geo_id = ReducedGeoId(geo_pos_id(geo_here)); geo_here.dist = _0; return(geo_here); }
geo FragmentShader(VertexOut vertex, Field <geo> Geo, Field <geo> OuterGeo) { geo geo_here = Geo[Here], geo_right = Geo[RightOne], geo_up = Geo[UpOne], geo_left = Geo[LeftOne], geo_down = Geo[DownOne], geo_up_right = Geo[UpRight], geo_up_left = Geo[UpLeft], geo_down_right = Geo[DownRight], geo_down_left = Geo[DownLeft]; geo outer_geo_here = OuterGeo[Here]; if (IsValid(geo_here.dir)) { return(geo_here); } outer_geo_here.dist = _255; // Start off as maximum possible 1-byte distance, since we will be taking the min of surrounding distances (and adding _1) if (outer_geo_here.dist > geo_right.dist && IsValid(geo_right.dir)) { InheritsFrom(ref outer_geo_here, geo_right); } else if (outer_geo_here.dist > geo_up.dist && IsValid(geo_up.dir)) { InheritsFrom(ref outer_geo_here, geo_up); } else if (outer_geo_here.dist > geo_left.dist && IsValid(geo_left.dir)) { InheritsFrom(ref outer_geo_here, geo_left); } else if (outer_geo_here.dist > geo_down.dist && IsValid(geo_down.dir)) { InheritsFrom(ref outer_geo_here, geo_down); } else if (outer_geo_here.dist > geo_up_right.dist && IsValid(geo_up_right.dir)) { InheritsFrom(ref outer_geo_here, geo_up_right); } else if (outer_geo_here.dist > geo_up_left.dist && IsValid(geo_up_left.dir)) { InheritsFrom(ref outer_geo_here, geo_up_left); } else if (outer_geo_here.dist > geo_down_right.dist && IsValid(geo_down_right.dir)) { InheritsFrom(ref outer_geo_here, geo_down_right); } else if (outer_geo_here.dist > geo_down_left.dist && IsValid(geo_down_left.dir)) { InheritsFrom(ref outer_geo_here, geo_down_left); } return(outer_geo_here); }
tile FragmentShader(VertexOut vertex, Field <tile> Tiles, Field <geo> Geo) { tile tile_here = Tiles[Here]; geo geo_here = Geo[Here]; if (IsValid(geo_here.dir)) { tile_here.type = TileType.Trees; } return(tile_here); }
geo FragmentShader(VertexOut vertex, Field <geo> Geo) { geo here = Geo[Here]; if (here.dir == _0) { return(here); } vec2 pos = vertex.TexCoords * Geo.Size; set_geo_pos_id(ref here, pos); return(here); }
dirward FragmentShader(VertexOut vertex, Field <dirward> Dirward, Field <geo> Geo, Field <geo> ShiftedGeo, Field <geo_info> Info, Field <geo_info> ShiftedInfo, [Dir.Vals] float dir) { geo geo_here = Geo[Here], geo_shift = ShiftedGeo[Here]; if (geo_here.dir == _0) { return(dirward.Nothing); } geo_info info_here = Info[Here], info_shift = ShiftedInfo[Here]; if (geo_here.pos_storage != geo_shift.pos_storage) { return(Dirward[Here]); } float dist_here = unpack_val(info_here.xy), dist_shift = unpack_val(info_shift.xy), circum = unpack_val(info_here.zw); float diff = dist_here - dist_shift; float clockwise = 0, counterclockwise = 0; if (diff > 0) { clockwise = diff; counterclockwise = circum - diff; } else { clockwise = circum + diff; counterclockwise = -diff; } dirward output = dirward.Nothing; output.polarity = clockwise > counterclockwise ? 0 : 1; output.polarity_set = _true; return(output); }
color FragmentShader(VertexOut vertex, Field <geo> Geo, Field <vec4> PolarDistance, PointSampler Texture) { color output = color.TransparentBlack; geo here = Geo[Here]; float dist = 0; vec2 subcell_pos = get_subcell_pos(vertex, Geo.Size); if (here.dir > _0) { if (subcell_pos > vec(.5f, .5f)) { vec2 subcell_pos_1 = get_subcell_pos(vertex, Geo.Size * 2); output += DrawDebugNum(unpack_val(PolarDistance[Here].xy), subcell_pos_1, Texture) * rgb(0xFF8080); } if (subcell_pos < vec(.5f, .5f)) { vec2 subcell_pos_2 = get_subcell_pos(vertex, Geo.Size * 2); output += DrawDebugNum(unpack_val(PolarDistance[Here].zw), subcell_pos_2, Texture) * rgb(0xFF8080); } return(output); } if (subcell_pos.y > .5) { dist = unpack_val(PolarDistance[Here].xy); } else { dist = unpack_val(PolarDistance[Here].zw); } if (here.dir > _0) { dist = dist / 1024.0f; output = (color)vec(dist, dist, dist, 1.0f); } return(output); }
geo_info FragmentShader(VertexOut vertex, Field <geo> Geo, Field <geo_info> Info) { geo_info info_here = Info[Here]; geo here = Geo[Here]; if (here.dir == _0) { return(geo_info.Zero); } vec2 pos_here = vertex.TexCoords * Geo.Size; vec2 start_pos = geo_pos_id(here); RelativeIndex GeoStart = (RelativeIndex)(start_pos - pos_here); geo right = Geo[GeoStart + RightOne], up = Geo[GeoStart + UpOne], left = Geo[GeoStart + LeftOne], down = Geo[GeoStart + DownOne]; float circum = 0; if (right.pos_storage == here.pos_storage) { circum = max(circum, polar_dist(Info[GeoStart + RightOne])); } if (up.pos_storage == here.pos_storage) { circum = max(circum, polar_dist(Info[GeoStart + UpOne])); } if (left.pos_storage == here.pos_storage) { circum = max(circum, polar_dist(Info[GeoStart + LeftOne])); } if (down.pos_storage == here.pos_storage) { circum = max(circum, polar_dist(Info[GeoStart + DownOne])); } // Pack the polar circumference into 2-bytes set_circumference(ref info_here, circum); return(info_here); }
dirward FragmentShader(VertexOut vertex, Field <dirward> Dirward, Field <geo> Geo) { geo here = Geo[Here], right = Geo[RightOne], up = Geo[UpOne], left = Geo[LeftOne], down = Geo[DownOne]; dirward dirward_here = Dirward[Here], dirward_right = Dirward[RightOne], dirward_up = Dirward[UpOne], dirward_left = Dirward[LeftOne], dirward_down = Dirward[DownOne]; if (here.dir == _0) { return(dirward.Nothing); } if (dirward_here.polarity_set == _false) { if (right.pos_storage == here.pos_storage && dirward_right.polarity_set == _true) { dirward_here.polarity = dirward_right.polarity; dirward_here.polarity_set = _true; } if (left.pos_storage == here.pos_storage && dirward_left.polarity_set == _true) { dirward_here.polarity = dirward_left.polarity; dirward_here.polarity_set = _true; } if (up.pos_storage == here.pos_storage && dirward_up.polarity_set == _true) { dirward_here.polarity = dirward_up.polarity; dirward_here.polarity_set = _true; } if (down.pos_storage == here.pos_storage && dirward_down.polarity_set == _true) { dirward_here.polarity = dirward_down.polarity; dirward_here.polarity_set = _true; } } return(dirward_here); }
extra FragmentShader(VertexOut vertex, Field <data> Data, Field <extra> Extra, Field <geo> Geo, Field <geo> AntiGeo) { data data_here = Data[Here]; extra extra_here = Extra[Here]; geo geo_here = Geo[Here]; if (data_here.change >= SetPolarity.Counterclockwise) { extra_here.geo_id = geo_here.geo_id; extra_here.polarity_set = _true; extra_here.polarity = Polarity.Counterclockwise; } else if (data_here.change >= SetPolarity.Clockwise) { extra_here.geo_id = geo_here.geo_id; extra_here.polarity_set = _true; extra_here.polarity = Polarity.Clockwise; } return(extra_here); }
void NaivePathfind(VertexOut vertex, Field <data> Current, Field <data> Previous, Field <vec4> TargetData, Field <extra> Extra, Field <vec4> RandomField, Field <geo> Geo, Field <geo> AntiGeo, Field <dirward> DirwardRight, Field <dirward> DirwardLeft, Field <dirward> DirwardUp, Field <dirward> DirwardDown, unit data, ref data here) { // Get geodesic info (of both polarities) geo geo_here = Geo[Here], antigeo_here = AntiGeo[Here]; // Unpack packed info vec4 target = TargetData[Here]; vec2 CurPos = floor((vertex.TexCoords * TargetData.Size + vec(.5f, .5f))); vec2 Destination = floor(unpack_vec2((vec4)target)); // Get nearby units data right = Current[RightOne], up = Current[UpOne], left = Current[LeftOne], down = Current[DownOne]; data prev_right = Previous[RightOne], prev_up = Previous[UpOne], prev_left = Previous[LeftOne], prev_down = Previous[DownOne]; extra extra_here = Extra[Here]; // Calculate primary and secondary direction to travel (dir1 and dir2 respectively) float dir1 = Dir.None, dir2 = Dir.None; if (Destination.x > CurPos.x + .75f) { dir1 = Dir.Right; } if (Destination.x < CurPos.x - .75f) { dir1 = Dir.Left; } if (Destination.y > CurPos.y + .75f) { dir1 = Dir.Up; } if (Destination.y < CurPos.y - .75f) { dir1 = Dir.Down; } vec2 diff = Destination - CurPos; vec2 mag = abs(diff); float prior_dir = Dir.None; bool blocked1 = false; if (mag.x > mag.y && Destination.x > CurPos.x + 1) { dir1 = Dir.Right; blocked1 = Something(right) || Something(prev_right) && prior_dir != Dir.Left; } if (mag.y > mag.x && Destination.y > CurPos.y + 1) { dir1 = Dir.Up; blocked1 = Something(up) || Something(prev_up) && prior_dir != Dir.Down; } if (mag.x > mag.y && Destination.x < CurPos.x - 1) { dir1 = Dir.Left; blocked1 = Something(left) || Something(prev_left) && prior_dir != Dir.Right; } if (mag.y > mag.x && Destination.y < CurPos.y - 1) { dir1 = Dir.Down; blocked1 = Something(down) || Something(prev_down) && prior_dir != Dir.Up; } bool blocked2 = false; if (dir1 == Dir.Right || dir1 == Dir.Left) { if (Destination.y > CurPos.y + 0) { dir2 = Dir.Up; blocked2 = Something(up) || Something(prev_up) && prior_dir != Dir.Down; } else if (Destination.y < CurPos.y - 0) { dir2 = Dir.Down; blocked2 = Something(down) || Something(prev_down) && prior_dir != Dir.Up; } } if (dir1 == Dir.Up || dir1 == Dir.Down) { if (Destination.x > CurPos.x + 0) { dir2 = Dir.Right; blocked2 = Something(right) || Something(prev_right) && prior_dir != Dir.Left; } else if (Destination.x < CurPos.x - 0) { dir2 = Dir.Left; blocked2 = Something(left) || Something(prev_left) && prior_dir != Dir.Right; } } // Get current coordinate vec2 pos_here = vertex.TexCoords * Geo.Size; // Get dirward extensions for each direction, as well as whether we need to cross over an obstacle to get to where we want to go in that direction. dirward dirward_here1 = dirward.Nothing; dirward dirward_here2 = dirward.Nothing; bool other_side1 = GetDirward(ref dirward_here1, dir1, ref Destination, ref pos_here, DirwardRight, DirwardLeft, DirwardUp, DirwardDown); bool other_side2 = GetDirward(ref dirward_here2, dir2, ref Destination, ref pos_here, DirwardRight, DirwardLeft, DirwardUp, DirwardDown); // Get polarity based on the dirward extensions float polarity1 = dirward_here1.polarity, polarity2 = dirward_here2.polarity, chosen_polarity = Polarity.Undefined; // If this unit has already picked a polarity for this geodesic area, then we will stick with that polarity if (extra_here.geo_id == geo_here.geo_id && extra_here.polarity_set == _true) { polarity1 = extra_here.polarity; polarity2 = extra_here.polarity; } // Get geodesic info associated with primary and secondary direction (geo1 for dir1 and geo2 for dir2) geo geo1 = polarity1 == Polarity.Counterclockwise ? antigeo_here : geo_here, geo2 = polarity2 == Polarity.Counterclockwise ? antigeo_here : geo_here; // Check if we should follow the geodesic we are on vec2 geo_id = geo1.geo_id; bool use_simple_pathing = false; if (geo1.dir > 0 && ValidDirward(dirward_here1) && other_side1 && dirward_here1.geo_id == geo_id && (/*geo1.dist == _0 ||*/ blocked1 || extra_here.polarity_set == _true && extra_here.geo_id == geo1.geo_id)) { dir1 = geo1.dir; chosen_polarity = polarity1; } else if (geo2.dir > 0 && ValidDirward(dirward_here2) && other_side2 && dirward_here2.geo_id == geo_id && (/*geo2.dist == _0 || */ blocked2 || extra_here.polarity_set == _true && extra_here.geo_id == geo2.geo_id)) { dir1 = geo2.dir; chosen_polarity = other_side1 && ValidDirward(dirward_here1) ? polarity1 : polarity2; } else { // If not, then use Simple Pathing use_simple_pathing = true; } // If geodesic pathfinding has us running into something... if (!use_simple_pathing && (Something(Current[dir_to_vec(dir1)]) || geo1.dist > _0) && geo1.dist < 1) { // Turn inward toward the obstacles, if that direction is open float alt_dir; if (chosen_polarity == Polarity.Clockwise) { alt_dir = RotateLeft(dir1); } else { alt_dir = RotateRight(dir1); } if (!Something(Current[dir_to_vec(alt_dir)]) && !Something(Previous[dir_to_vec(alt_dir)])) { dir1 = alt_dir; } } if (use_simple_pathing) { // Go toward the cardinal direction that is furthest away. If something is in your way, go perpendicularly, assuming you also need to go in that direction. if ((mag.x > mag.y || diff.y > 0 && Something(up) || diff.y < 0 && Something(down)) && Destination.x > CurPos.x + 1 && !Something(right)) { dir1 = Dir.Right; } if ((mag.y > mag.x || diff.x > 0 && Something(right) || diff.x < 0 && Something(left)) && Destination.y > CurPos.y + 1 && !Something(up)) { dir1 = Dir.Up; } if ((mag.x > mag.y || diff.y > 0 && Something(up) || diff.y < 0 && Something(down)) && Destination.x < CurPos.x - 1 && !Something(left)) { dir1 = Dir.Left; } if ((mag.y > mag.x || diff.x > 0 && Something(right) || diff.x < 0 && Something(left)) && Destination.y < CurPos.y - 1 && !Something(down)) { dir1 = Dir.Down; } } // If something is in the way of the direction we want to go... if (IsValid(dir1) && Something(Current[dir_to_vec(dir1)])) { // ...and we are using geodesic pathfinding and have a determined polarity... if (chosen_polarity != Polarity.Undefined && !use_simple_pathing) { // ... then if some up or right from us has polarity set, let's follow their polarity (to avoid traffic jams) extra extra_right = Extra[RightOne], extra_up = Extra[UpOne]; // If someone right of us has polarity set, follow them if (extra_right.polarity_set == _true) { chosen_polarity = extra_right.polarity; } // If someone above us has polarity set, follow them if (extra_up.polarity_set == _true) { chosen_polarity = extra_up.polarity; } use_simple_pathing = false; } // ... and occasionally choose random direction instead (assuming we aren't surrounded) vec4 rnd = RandomField[Here]; if (rnd.x < .1f && !(Something(right) && Something(left) && Something(up) && Something(down))) { dir1 = RndFint(rnd.y, Dir.Right, Dir.Down); } } // Final sanity check on direction we want to follow if (IsValid(dir1)) { here.direction = dir1; // If we are choosing a polarity then we need to store it if (chosen_polarity != Polarity.Undefined && !use_simple_pathing) { // The polarity is stored in "extra", not "data", so we create a signal pumped into this "data" that will be used to modify the "extra" on a subsequent pass. here.change += chosen_polarity == Polarity.Counterclockwise ? SetPolarity.Counterclockwise : SetPolarity.Clockwise; } } else { // If we don't have a valid direction and we're attack-moving, then we probably arrived at our destination, so let's guard for now. if (here.action == UnitAction.Attacking) { here.action = UnitAction.Guard; } } }
dirward FragmentShader(VertexOut vertex, Field <tile> Tiles, Field <geo> Geo, Field <dirward> Dirward, [Dir.Vals] float dir) { tile here = Tiles[Here]; geo geo_here = Geo[Here], geo_right = Geo[RightOne], geo_up = Geo[UpOne], geo_left = Geo[LeftOne], geo_down = Geo[DownOne], geo_up_right = Geo[UpRight], geo_up_left = Geo[UpLeft], geo_down_right = Geo[DownRight], geo_down_left = Geo[DownLeft]; dirward dirward_here = Dirward[Here], dirward_right = Dirward[RightOne], dirward_up = Dirward[UpOne], dirward_left = Dirward[LeftOne], dirward_down = Dirward[DownOne], dirward_up_right = Dirward[UpRight], dirward_up_left = Dirward[UpLeft], dirward_down_right = Dirward[DownRight], dirward_down_left = Dirward[DownLeft]; if (IsBlockingTile(here)) { return(dirward.Nothing); } dirward output = dirward.Nothing; dirward forward = dirward.Nothing, forward_right = dirward.Nothing, forward_left = dirward.Nothing, rightward = dirward.Nothing, leftward = dirward.Nothing; geo geo_forward = geo.Nothing, geo_forward_right = geo.Nothing, geo_forward_left = geo.Nothing, geo_rightward = geo.Nothing, geo_leftward = geo.Nothing; // Get the surrounding dirward info and store it relative to the direction we consider forward if (dir == Dir.Up) { forward = dirward_up; forward_right = dirward_up_right; forward_left = dirward_up_left; rightward = dirward_right; leftward = dirward_left; geo_forward = geo_up; geo_forward_right = geo_up_right; geo_forward_left = geo_up_left; geo_rightward = geo_right; geo_leftward = geo_left; } else if (dir == Dir.Right) { forward = dirward_right; forward_right = dirward_down_right; forward_left = dirward_up_right; rightward = dirward_down; leftward = dirward_up; geo_forward = geo_right; geo_forward_right = geo_down_right; geo_forward_left = geo_up_right; geo_rightward = geo_down; geo_leftward = geo_up; } else if (dir == Dir.Down) { forward = dirward_down; forward_right = dirward_down_left; forward_left = dirward_down_right; rightward = dirward_left; leftward = dirward_right; geo_forward = geo_down; geo_forward_right = geo_down_left; geo_forward_left = geo_down_right; geo_rightward = geo_left; geo_leftward = geo_right; } else if (dir == Dir.Left) { forward = dirward_left; forward_right = dirward_up_left; forward_left = dirward_down_left; rightward = dirward_up; leftward = dirward_down; geo_forward = geo_left; geo_forward_right = geo_up_left; geo_forward_left = geo_down_left; geo_rightward = geo_up; geo_leftward = geo_down; } if (geo_here.dir > 0 && IsBlockingTile(Tiles[dir_to_vec(dir)])) { output = dirward_here; output.geo_id = geo_here.geo_id; output.dist_to_wall = _0; } else if (ValidDirward(forward) && forward.geo_id == geo_forward.geo_id) { output = forward; output.dist_to_wall += _1; } else if (ValidDirward(forward_right) && forward_right.geo_id == geo_forward_right.geo_id) { output = forward_right; output.dist_to_wall += _1; } else if (ValidDirward(forward_left) && forward_left.geo_id == geo_forward_left.geo_id) { output = forward_left; output.dist_to_wall += _1; } //else if (ValidDirward(rightward) && rightward.geo_id == geo_rightward.geo_id) { output = rightward; output.dist_to_wall += _0; } //else if (ValidDirward(leftward) && leftward.geo_id == geo_leftward.geo_id) { output = leftward; output.dist_to_wall += _0; } return(output); }
protected static vec2 geo_pos_id(geo g) { return(unpack_vec2_3byte(g.pos_storage)); }
protected static void set_geo_pos_id(ref geo g, vec2 pos) { g.pos_storage = pack_vec2_3byte(pos); }
geo FragmentShader(VertexOut vertex, Field <tile> Tiles, Field <geo> Geo, [Vals.Bool] bool Anti) { tile here = Tiles[Here], right = Tiles[RightOne], up = Tiles[UpOne], left = Tiles[LeftOne], down = Tiles[DownOne], up_right = Tiles[UpRight], up_left = Tiles[UpLeft], down_right = Tiles[DownRight], down_left = Tiles[DownLeft]; geo geo_here = Geo[Here], geo_right = Geo[RightOne], geo_up = Geo[UpOne], geo_left = Geo[LeftOne], geo_down = Geo[DownOne], geo_up_right = Geo[UpRight], geo_up_left = Geo[UpLeft], geo_down_right = Geo[DownRight], geo_down_left = Geo[DownLeft]; if (IsBlockingTile(here)) { return(geo.Nothing); } geo output = geo_here; if (!(IsBlockingTile(right) && IsBlockingTile(left)) && (geo_here.dir == Dir.Up && geo_up.dir == Dir.Down || geo_here.dir == Dir.Down && geo_down.dir == Dir.Up)) { output.dir = IsBlockingTile(right) ? Dir.Left : Dir.Right; } if (!(IsBlockingTile(up) && IsBlockingTile(down)) && (geo_here.dir == Dir.Right && geo_right.dir == Dir.Left || geo_here.dir == Dir.Left && geo_left.dir == Dir.Right)) { output.dir = IsBlockingTile(up) ? Dir.Down : Dir.Up; } if (Geo[dir_to_vec(output.dir)].bad == _true && geo_here.bad == _false) { output.dir = Reverse(output.dir); } int surround_count = (IsBlockingTile(up) ? 1 : 0) + (IsBlockingTile(left) ? 1 : 0) + (IsBlockingTile(down) ? 1 : 0) + (IsBlockingTile(right) ? 1 : 0); float bad_count = geo_up.bad + geo_left.bad + geo_down.bad + geo_right.bad; if (surround_count >= 2 && bad_count >= _1 || geo_up.bad == _true && geo_down.bad == _true || geo_right.bad == _true && geo_left.bad == _true) { output.bad = _true; } return(output); }
geo FragmentShader(VertexOut vertex, Field <geo> Geo) { geo here = Geo[Here], right = Geo[RightOne], up = Geo[UpOne], left = Geo[LeftOne], down = Geo[DownOne], up_right = Geo[UpRight], up_left = Geo[UpLeft], down_right = Geo[DownRight], down_left = Geo[DownLeft]; if (here.dir == _0) { return(here); } vec2 extr_here = geo_pos_id(here), extr_right = geo_pos_id(right), extr_up = geo_pos_id(up), extr_left = geo_pos_id(left), extr_down = geo_pos_id(down), extr_up_right = geo_pos_id(up_right), extr_up_left = geo_pos_id(up_left), extr_down_right = geo_pos_id(down_right), extr_down_left = geo_pos_id(down_left); float val_here = flatten(extr_here), val_right = flatten(extr_right), val_up = flatten(extr_up), val_left = flatten(extr_left), val_down = flatten(extr_down), val_up_right = flatten(extr_up_right), val_up_left = flatten(extr_up_left), val_down_right = flatten(extr_down_right), val_down_left = flatten(extr_down_left); if (val_here < val_right) { here.pos_storage = right.pos_storage; val_here = val_right; } if (val_here < val_up) { here.pos_storage = up.pos_storage; val_here = val_up; } if (val_here < val_left) { here.pos_storage = left.pos_storage; val_here = val_left; } if (val_here < val_down) { here.pos_storage = down.pos_storage; val_here = val_down; } if (val_here < val_up_right) { here.pos_storage = up_right.pos_storage; val_here = val_up_right; } if (val_here < val_up_left) { here.pos_storage = up_left.pos_storage; val_here = val_up_left; } if (val_here < val_down_right) { here.pos_storage = down_right.pos_storage; val_here = val_down_right; } if (val_here < val_down_left) { here.pos_storage = down_left.pos_storage; val_here = val_down_left; } return(here); }
void InheritsFrom(ref geo outer_geo, geo inner_geo) { outer_geo.dist = inner_geo.dist + _1; outer_geo.geo_id = inner_geo.geo_id; }
geo_info FragmentShader(VertexOut vertex, Field <geo> Geo, Field <geo_info> Info) { geo here = Geo[Here], right = Geo[RightOne], up = Geo[UpOne], left = Geo[LeftOne], down = Geo[DownOne]; float dist_right = polar_dist(Info[RightOne]), dist_up = polar_dist(Info[UpOne]), dist_left = polar_dist(Info[LeftOne]), dist_down = polar_dist(Info[DownOne]); if (here.dir == _0) { return(geo_info.Zero); } float dist = 0; // Calculate the geo_id of this cell geo temp_geo = geo.Nothing; vec2 pos = vertex.TexCoords * Geo.Size; set_geo_pos_id(ref temp_geo, pos); // ... if that geo_id matches the id of the geo info here, then this is the "master" or "12 o' clock" cell of the geodesic line going through this cell. if (here.pos_storage == temp_geo.pos_storage) { // That means its polar distance is 0 by definition. dist = 0; } else { // If this geodesic flows into another tile, then the polar distance here should be 1 less than the distance of the tile it flows into. // This is a fail safe condition that covers degenerate tiles which have nothing flowing into them and only flow out. if (here.dir == Dir.Left) { dist = max(_0, dist_left - 1); } if (here.dir == Dir.Right) { dist = max(_0, dist_right - 1); } if (here.dir == Dir.Up) { dist = max(_0, dist_up - 1); } if (here.dir == Dir.Down) { dist = max(_0, dist_down - 1); } // The polar distance is also 1 plus the polar distance of whatever cell comes "before" it (by following the geo backwards "counterclockwise"). if (right.dir == Dir.Left && dist_right >= dist) { dist = dist_right + 1; } if (left.dir == Dir.Right && dist_left >= dist) { dist = dist_left + 1; } if (up.dir == Dir.Down && dist_up >= dist) { dist = dist_up + 1; } if (down.dir == Dir.Up && dist_down >= dist) { dist = dist_down + 1; } } // Pack the polar distance into 2-bytes and return it in geo_info output = geo_info.Zero; set_polar_dist(ref output, dist); return(output); }
geo FragmentShader(VertexOut vertex, Field <tile> Tiles, [Vals.Bool] bool Anti) { tile here = Tiles[Here], right = Tiles[RightOne], up = Tiles[UpOne], left = Tiles[LeftOne], down = Tiles[DownOne], up_right = Tiles[UpRight], up_left = Tiles[UpLeft], down_right = Tiles[DownRight], down_left = Tiles[DownLeft]; if (IsBlockingTile(here)) { return(geo.Nothing); } float dir = 0; if (IsBlockingTile(up_left)) { dir = Anti ? Dir.Left : Dir.Up; } if (IsBlockingTile(up_right)) { dir = Anti ? Dir.Up : Dir.Right; } if (IsBlockingTile(down_right)) { dir = Anti ? Dir.Right : Dir.Down; } if (IsBlockingTile(down_left)) { dir = Anti ? Dir.Down : Dir.Left; } if (Anti) { if (IsBlockingTile(right)) { dir = Dir.Up; if (IsBlockingTile(up)) { dir = Dir.Left; if (IsBlockingTile(left)) { dir = Dir.Down; } } } if (IsBlockingTile(up)) { dir = Dir.Left; if (IsBlockingTile(left)) { dir = Dir.Down; if (IsBlockingTile(down)) { dir = Dir.Right; } } } if (IsBlockingTile(left)) { dir = Dir.Down; if (IsBlockingTile(down)) { dir = Dir.Right; if (IsBlockingTile(right)) { dir = Dir.Up; } } } if (IsBlockingTile(down)) { dir = Dir.Right; if (IsBlockingTile(right)) { dir = Dir.Up; if (IsBlockingTile(up)) { dir = Dir.Left; } } } } else { if (IsBlockingTile(right)) { dir = Dir.Down; if (IsBlockingTile(down)) { dir = Dir.Left; if (IsBlockingTile(left)) { dir = Dir.Up; } } } if (IsBlockingTile(up)) { dir = Dir.Right; if (IsBlockingTile(right)) { dir = Dir.Down; if (IsBlockingTile(down)) { dir = Dir.Left; } } } if (IsBlockingTile(left)) { dir = Dir.Up; if (IsBlockingTile(up)) { dir = Dir.Right; if (IsBlockingTile(right)) { dir = Dir.Down; } } } if (IsBlockingTile(down)) { dir = Dir.Left; if (IsBlockingTile(left)) { dir = Dir.Up; if (IsBlockingTile(up)) { dir = Dir.Right; } } } } geo output = geo.Nothing; output.dir = dir; int surround_count = (IsBlockingTile(up) ? 1 : 0) + (IsBlockingTile(left) ? 1 : 0) + (IsBlockingTile(down) ? 1 : 0) + (IsBlockingTile(right) ? 1 : 0); if (output.dir > _0 && surround_count == 3) { output.bad = _true; } return(output); }