123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087 |
- using System.Collections.Generic;
- using Math = System.Math;
- using UnityEngine;
- using UnityEngine.Profiling;
- namespace Pathfinding {
- using Pathfinding.Serialization;
- using Pathfinding.Util;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonOptIn]
- [Pathfinding.Util.Preserve]
- public class GridGraph : NavGraph, IUpdatableGraph, ITransformedGraph
- , IRaycastableGraph {
-
- protected override void OnDestroy () {
- base.OnDestroy();
-
- RemoveGridGraphFromStatic();
- }
- protected override void DestroyAllNodes () {
- GetNodes(node => {
-
-
-
-
- (node as GridNodeBase).ClearCustomConnections(true);
- node.ClearConnections(false);
- node.Destroy();
- });
- }
- void RemoveGridGraphFromStatic () {
- var graphIndex = active.data.GetGraphIndex(this);
- GridNode.ClearGridGraph(graphIndex, this);
- }
-
-
-
-
-
- public virtual bool uniformWidthDepthGrid {
- get {
- return true;
- }
- }
-
-
-
-
-
- public virtual int LayerCount {
- get {
- return 1;
- }
- }
- public override int CountNodes () {
- return nodes != null ? nodes.Length : 0;
- }
- public override void GetNodes (System.Action<GraphNode> action) {
- if (nodes == null) return;
- for (int i = 0; i < nodes.Length; i++) action(nodes[i]);
- }
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public InspectorGridMode inspectorGridMode = InspectorGridMode.Grid;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public InspectorGridHexagonNodeSize inspectorHexagonSizeMode = InspectorGridHexagonNodeSize.Width;
-
- public int width;
-
- public int depth;
-
-
-
-
- [JsonMember]
- public float aspectRatio = 1F;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public float isometricAngle;
-
- public static readonly float StandardIsometricAngle = 90-Mathf.Atan(1/Mathf.Sqrt(2))*Mathf.Rad2Deg;
-
- public static readonly float StandardDimetricAngle = Mathf.Acos(1/2f)*Mathf.Rad2Deg;
-
-
-
-
-
-
- [JsonMember]
- public bool uniformEdgeCosts;
-
- [JsonMember]
- public Vector3 rotation;
-
- [JsonMember]
- public Vector3 center;
-
- [JsonMember]
- public Vector2 unclampedSize;
-
-
-
-
- [JsonMember]
- public float nodeSize = 1;
-
-
- [JsonMember]
- public GraphCollision collision;
-
-
-
-
- [JsonMember]
- public float maxClimb = 0.4F;
-
- [JsonMember]
- public float maxSlope = 90;
-
-
-
-
- protected bool useRaycastNormal { get { return Math.Abs(90-maxSlope) > float.Epsilon; } }
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public int erodeIterations;
-
-
-
-
-
-
-
-
- [JsonMember]
- public bool erosionUseTags;
-
-
-
-
-
- [JsonMember]
- public int erosionFirstTag = 1;
-
-
-
-
-
-
- [JsonMember]
- public NumNeighbours neighbours = NumNeighbours.Eight;
-
-
-
-
-
- [JsonMember]
- public bool cutCorners = true;
-
-
-
-
- [JsonMember]
- public float penaltyPositionOffset;
-
- [JsonMember]
- public bool penaltyPosition;
-
-
-
-
- [JsonMember]
- public float penaltyPositionFactor = 1F;
- [JsonMember]
- public bool penaltyAngle;
-
-
-
-
-
-
- [JsonMember]
- public float penaltyAngleFactor = 100F;
-
- [JsonMember]
- public float penaltyAnglePower = 1;
-
-
-
-
-
-
-
- [JsonMember]
- public bool useJumpPointSearch;
-
- [JsonMember]
- public bool showMeshOutline = true;
-
- [JsonMember]
- public bool showNodeConnections;
-
- [JsonMember]
- public bool showMeshSurface = true;
-
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public TextureData textureData = new TextureData();
-
-
-
-
-
- public Vector2 size { get; protected set; }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.NonSerialized]
- public readonly int[] neighbourOffsets = new int[8];
-
- [System.NonSerialized]
- public readonly uint[] neighbourCosts = new uint[8];
-
- [System.NonSerialized]
- public readonly int[] neighbourXOffsets = new int[8];
-
- [System.NonSerialized]
- public readonly int[] neighbourZOffsets = new int[8];
-
- internal static readonly int[] hexagonNeighbourIndices = { 0, 1, 5, 2, 3, 7 };
-
- public const int getNearestForceOverlap = 2;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public GridNodeBase[] nodes;
-
-
-
-
- public GraphTransform transform { get; private set; }
-
-
-
-
-
-
-
- public bool is2D {
- get {
- return Quaternion.Euler(this.rotation) * Vector3.up == -Vector3.forward;
- }
- set {
- if (value != is2D) {
- this.rotation = value ? new Vector3(this.rotation.y - 90, 270, 90) : new Vector3(0, this.rotation.x + 90, 0);
- }
- }
- }
-
- public class TextureData {
- public bool enabled;
- public Texture2D source;
- public float[] factors = new float[3];
- public ChannelUse[] channels = new ChannelUse[3];
- Color32[] data;
-
- public void Initialize () {
- if (enabled && source != null) {
- for (int i = 0; i < channels.Length; i++) {
- if (channels[i] != ChannelUse.None) {
- try {
- data = source.GetPixels32();
- } catch (UnityException e) {
- Debug.LogWarning(e.ToString());
- data = null;
- }
- break;
- }
- }
- }
- }
-
- public void Apply (GridNodeBase node, int x, int z) {
- if (enabled && data != null && x < source.width && z < source.height) {
- Color32 col = data[z*source.width+x];
- if (channels[0] != ChannelUse.None) {
- ApplyChannel(node, x, z, col.r, channels[0], factors[0]);
- }
- if (channels[1] != ChannelUse.None) {
- ApplyChannel(node, x, z, col.g, channels[1], factors[1]);
- }
- if (channels[2] != ChannelUse.None) {
- ApplyChannel(node, x, z, col.b, channels[2], factors[2]);
- }
- node.WalkableErosion = node.Walkable;
- }
- }
-
- void ApplyChannel (GridNodeBase node, int x, int z, int value, ChannelUse channelUse, float factor) {
- switch (channelUse) {
- case ChannelUse.Penalty:
- node.Penalty += (uint)Mathf.RoundToInt(value*factor);
- break;
- case ChannelUse.Position:
- node.position = GridNode.GetGridGraph(node.GraphIndex).GraphPointToWorld(x, z, value);
- break;
- case ChannelUse.WalkablePenalty:
- if (value == 0) {
- node.Walkable = false;
- } else {
- node.Penalty += (uint)Mathf.RoundToInt((value-1)*factor);
- }
- break;
- }
- }
- public enum ChannelUse {
- None,
- Penalty,
- Position,
- WalkablePenalty,
- }
- }
- public GridGraph () {
- unclampedSize = new Vector2(10, 10);
- nodeSize = 1F;
- collision = new GraphCollision();
- transform = new GraphTransform(Matrix4x4.identity);
- }
- public override void RelocateNodes (Matrix4x4 deltaMatrix) {
-
- throw new System.Exception("This method cannot be used for Grid Graphs. Please use the other overload of RelocateNodes instead");
- }
-
-
-
-
- public void RelocateNodes (Vector3 center, Quaternion rotation, float nodeSize, float aspectRatio = 1, float isometricAngle = 0) {
- var previousTransform = transform;
- this.center = center;
- this.rotation = rotation.eulerAngles;
- this.aspectRatio = aspectRatio;
- this.isometricAngle = isometricAngle;
- SetDimensions(width, depth, nodeSize);
- GetNodes(node => {
- var gnode = node as GridNodeBase;
- var height = previousTransform.InverseTransform((Vector3)node.position).y;
- node.position = GraphPointToWorld(gnode.XCoordinateInGrid, gnode.ZCoordinateInGrid, height);
- });
- }
-
-
-
-
-
- public Int3 GraphPointToWorld (int x, int z, float height) {
- return (Int3)transform.Transform(new Vector3(x+0.5f, height, z+0.5f));
- }
- public static float ConvertHexagonSizeToNodeSize (InspectorGridHexagonNodeSize mode, float value) {
- if (mode == InspectorGridHexagonNodeSize.Diameter) value *= 1.5f/(float)System.Math.Sqrt(2.0f);
- else if (mode == InspectorGridHexagonNodeSize.Width) value *= (float)System.Math.Sqrt(3.0f/2.0f);
- return value;
- }
- public static float ConvertNodeSizeToHexagonSize (InspectorGridHexagonNodeSize mode, float value) {
- if (mode == InspectorGridHexagonNodeSize.Diameter) value *= (float)System.Math.Sqrt(2.0f)/1.5f;
- else if (mode == InspectorGridHexagonNodeSize.Width) value *= (float)System.Math.Sqrt(2.0f/3.0f);
- return value;
- }
- public int Width {
- get {
- return width;
- }
- set {
- width = value;
- }
- }
- public int Depth {
- get {
- return depth;
- }
- set {
- depth = value;
- }
- }
- public uint GetConnectionCost (int dir) {
- return neighbourCosts[dir];
- }
-
- [System.Obsolete("Use GridNode.HasConnectionInDirection instead")]
- public GridNode GetNodeConnection (GridNode node, int dir) {
- if (!node.HasConnectionInDirection(dir)) return null;
- if (!node.EdgeNode) {
- return nodes[node.NodeInGridIndex + neighbourOffsets[dir]] as GridNode;
- } else {
- int index = node.NodeInGridIndex;
-
- int z = index/Width;
- int x = index - z*Width;
- return GetNodeConnection(index, x, z, dir);
- }
- }
-
- [System.Obsolete("Use GridNode.HasConnectionInDirection instead")]
- public bool HasNodeConnection (GridNode node, int dir) {
- if (!node.HasConnectionInDirection(dir)) return false;
- if (!node.EdgeNode) {
- return true;
- } else {
- int index = node.NodeInGridIndex;
- int z = index/Width;
- int x = index - z*Width;
- return HasNodeConnection(index, x, z, dir);
- }
- }
-
- [System.Obsolete("Use GridNode.SetConnectionInternal instead")]
- public void SetNodeConnection (GridNode node, int dir, bool value) {
- int index = node.NodeInGridIndex;
- int z = index/Width;
- int x = index - z*Width;
- SetNodeConnection(index, x, z, dir, value);
- }
-
-
-
-
-
-
-
-
- [System.Obsolete("Use GridNode.HasConnectionInDirection instead")]
- private GridNode GetNodeConnection (int index, int x, int z, int dir) {
- if (!nodes[index].HasConnectionInDirection(dir)) return null;
-
- int nx = x + neighbourXOffsets[dir];
- if (nx < 0 || nx >= Width) return null;
- int nz = z + neighbourZOffsets[dir];
- if (nz < 0 || nz >= Depth) return null;
- int nindex = index + neighbourOffsets[dir];
- return nodes[nindex] as GridNode;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use GridNode.SetConnectionInternal instead")]
- public void SetNodeConnection (int index, int x, int z, int dir, bool value) {
- (nodes[index] as GridNode).SetConnectionInternal(dir, value);
- }
- [System.Obsolete("Use GridNode.HasConnectionInDirection instead")]
- public bool HasNodeConnection (int index, int x, int z, int dir) {
- if (!nodes[index].HasConnectionInDirection(dir)) return false;
-
- int nx = x + neighbourXOffsets[dir];
- if (nx < 0 || nx >= Width) return false;
- int nz = z + neighbourZOffsets[dir];
- if (nz < 0 || nz >= Depth) return false;
- return true;
- }
-
-
-
-
-
-
-
-
-
-
-
- public void SetGridShape (InspectorGridMode shape) {
- switch (shape) {
- case InspectorGridMode.Grid:
- isometricAngle = 0;
- aspectRatio = 1;
- uniformEdgeCosts = false;
- if (neighbours == NumNeighbours.Six) neighbours = NumNeighbours.Eight;
- break;
- case InspectorGridMode.Hexagonal:
- isometricAngle = StandardIsometricAngle;
- aspectRatio = 1;
- uniformEdgeCosts = true;
- neighbours = NumNeighbours.Six;
- break;
- case InspectorGridMode.IsometricGrid:
- uniformEdgeCosts = false;
- if (neighbours == NumNeighbours.Six) neighbours = NumNeighbours.Eight;
- isometricAngle = StandardIsometricAngle;
- break;
- case InspectorGridMode.Advanced:
- default:
- break;
- }
- inspectorGridMode = shape;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void SetDimensions (int width, int depth, float nodeSize) {
- unclampedSize = new Vector2(width, depth)*nodeSize;
- this.nodeSize = nodeSize;
- UpdateTransform();
- }
-
- [System.Obsolete("Use SetDimensions instead")]
- public void UpdateSizeFromWidthDepth () {
- SetDimensions(width, depth, nodeSize);
- }
-
-
-
-
- [System.Obsolete("This method has been renamed to UpdateTransform")]
- public void GenerateMatrix () {
- UpdateTransform();
- }
-
-
-
-
-
-
-
-
-
-
-
- public void UpdateTransform () {
- CalculateDimensions(out width, out depth, out nodeSize);
- transform = CalculateTransform();
- }
-
-
-
-
-
- public GraphTransform CalculateTransform () {
- int newWidth, newDepth;
- float newNodeSize;
- CalculateDimensions(out newWidth, out newDepth, out newNodeSize);
-
-
- var isometricMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 45, 0), Vector3.one);
- isometricMatrix = Matrix4x4.Scale(new Vector3(Mathf.Cos(Mathf.Deg2Rad*isometricAngle), 1, 1)) * isometricMatrix;
- isometricMatrix = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, -45, 0), Vector3.one) * isometricMatrix;
-
-
-
- var boundsMatrix = Matrix4x4.TRS(center, Quaternion.Euler(rotation), new Vector3(aspectRatio, 1, 1)) * isometricMatrix;
-
-
-
- var m = Matrix4x4.TRS(boundsMatrix.MultiplyPoint3x4(-new Vector3(newWidth*newNodeSize, 0, newDepth*newNodeSize)*0.5F), Quaternion.Euler(rotation), new Vector3(newNodeSize*aspectRatio, 1, newNodeSize)) * isometricMatrix;
-
-
- return new GraphTransform(m);
- }
-
-
-
-
-
- void CalculateDimensions (out int width, out int depth, out float nodeSize) {
- var newSize = unclampedSize;
-
- newSize.x *= Mathf.Sign(newSize.x);
- newSize.y *= Mathf.Sign(newSize.y);
-
- nodeSize = Mathf.Max(this.nodeSize, newSize.x/1024F);
- nodeSize = Mathf.Max(this.nodeSize, newSize.y/1024F);
-
- newSize.x = newSize.x < nodeSize ? nodeSize : newSize.x;
- newSize.y = newSize.y < nodeSize ? nodeSize : newSize.y;
- size = newSize;
-
- width = Mathf.FloorToInt(size.x / nodeSize);
- depth = Mathf.FloorToInt(size.y / nodeSize);
-
- if (Mathf.Approximately(size.x / nodeSize, Mathf.CeilToInt(size.x / nodeSize))) {
- width = Mathf.CeilToInt(size.x / nodeSize);
- }
- if (Mathf.Approximately(size.y / nodeSize, Mathf.CeilToInt(size.y / nodeSize))) {
- depth = Mathf.CeilToInt(size.y / nodeSize);
- }
- }
- public override NNInfoInternal GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
- if (nodes == null || depth*width != nodes.Length) {
- return new NNInfoInternal();
- }
-
- position = transform.InverseTransform(position);
- float xf = position.x;
- float zf = position.z;
- int x = Mathf.Clamp((int)xf, 0, width-1);
- int z = Mathf.Clamp((int)zf, 0, depth-1);
- var nn = new NNInfoInternal(nodes[z*width+x]);
- float y = transform.InverseTransform((Vector3)nodes[z*width+x].position).y;
- nn.clampedPosition = transform.Transform(new Vector3(Mathf.Clamp(xf, x, x+1f), y, Mathf.Clamp(zf, z, z+1f)));
- return nn;
- }
- protected virtual GridNodeBase GetNearestFromGraphSpace (Vector3 positionGraphSpace) {
- if (nodes == null || depth*width != nodes.Length) {
- return null;
- }
- float xf = positionGraphSpace.x;
- float zf = positionGraphSpace.z;
- int x = Mathf.Clamp((int)xf, 0, width-1);
- int z = Mathf.Clamp((int)zf, 0, depth-1);
- return nodes[z*width+x];
- }
- public override NNInfoInternal GetNearestForce (Vector3 position, NNConstraint constraint) {
- if (nodes == null || depth*width*LayerCount != nodes.Length) {
- return new NNInfoInternal();
- }
-
- Vector3 globalPosition = position;
-
- position = transform.InverseTransform(position);
-
- float xf = position.x;
- float zf = position.z;
- int x = Mathf.Clamp((int)xf, 0, width-1);
- int z = Mathf.Clamp((int)zf, 0, depth-1);
- GridNodeBase minNode = null;
- var distanceXZ = constraint != null ? constraint.distanceXZ : false;
-
- float maxDist = constraint == null || constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistance : float.PositiveInfinity;
- float minDistSqr = maxDist*maxDist;
- var layerCount = LayerCount;
- var layerStride = width*depth;
-
- for (int y = 0; y < layerCount; y++) {
- var node = nodes[z*width + x + layerStride*y];
- if (node != null && (constraint == null || constraint.Suitable(node))) {
- float dist = distanceXZ
- ? nodeSize*nodeSize * ((x + 0.5f - xf)*(x + 0.5f - xf) + (z + 0.5f - zf)*(z + 0.5f - zf))
- : ((Vector3)node.position-globalPosition).sqrMagnitude;
- if (dist <= minDistSqr) {
-
- minDistSqr = dist;
- minNode = node;
- }
- }
- }
-
- for (int w = 1;; w++) {
-
-
-
-
- if (nodeSize*nodeSize*w*w > minDistSqr*2) {
- break;
- }
- bool anyInside = false;
- int nx = x + w;
- int nz = z;
- int dx = -1;
- int dz = 1;
- for (int d = 0; d < 4; d++) {
- for (int i = 0; i < w; i++) {
- if (nx >= 0 && nz >= 0 && nx < width && nz < depth) {
- anyInside = true;
- var nodeIndex = nx+nz*width;
- for (int y = 0; y < layerCount; y++) {
- var node = nodes[nodeIndex + layerStride*y];
- if (node != null && (constraint == null || constraint.Suitable(node))) {
- float dist = distanceXZ
- ? nodeSize*nodeSize * ((nx + 0.5f - xf)*(nx + 0.5f - xf) + (nz + 0.5f - zf)*(nz + 0.5f - zf))
- : ((Vector3)node.position-globalPosition).sqrMagnitude;
- if (dist <= minDistSqr) {
-
- minDistSqr = dist;
- minNode = node;
- }
- }
- }
- }
- nx += dx;
- nz += dz;
- }
-
- var ndx = -dz;
- var ndz = dx;
- dx = ndx;
- dz = ndz;
- }
-
-
-
- if (!anyInside) break;
- }
- var nn = new NNInfoInternal(null);
- if (minNode != null) {
-
- var nx = minNode.XCoordinateInGrid;
- var nz = minNode.ZCoordinateInGrid;
- nn.node = minNode;
- nn.clampedPosition = transform.Transform(new Vector3(Mathf.Clamp(xf, nx, nx+1f), transform.InverseTransform((Vector3)minNode.position).y, Mathf.Clamp(zf, nz, nz+1f)));
- }
- return nn;
- }
-
-
-
-
-
- public virtual void SetUpOffsetsAndCosts () {
-
- neighbourOffsets[0] = -width;
- neighbourOffsets[1] = 1;
- neighbourOffsets[2] = width;
- neighbourOffsets[3] = -1;
- neighbourOffsets[4] = -width+1;
- neighbourOffsets[5] = width+1;
- neighbourOffsets[6] = width-1;
- neighbourOffsets[7] = -width-1;
- uint straightCost = (uint)Mathf.RoundToInt(nodeSize*Int3.Precision);
-
- uint diagonalCost = uniformEdgeCosts ? straightCost : (uint)Mathf.RoundToInt(nodeSize*Mathf.Sqrt(2F)*Int3.Precision);
- neighbourCosts[0] = straightCost;
- neighbourCosts[1] = straightCost;
- neighbourCosts[2] = straightCost;
- neighbourCosts[3] = straightCost;
- neighbourCosts[4] = diagonalCost;
- neighbourCosts[5] = diagonalCost;
- neighbourCosts[6] = diagonalCost;
- neighbourCosts[7] = diagonalCost;
-
- neighbourXOffsets[0] = 0;
- neighbourXOffsets[1] = 1;
- neighbourXOffsets[2] = 0;
- neighbourXOffsets[3] = -1;
- neighbourXOffsets[4] = 1;
- neighbourXOffsets[5] = 1;
- neighbourXOffsets[6] = -1;
- neighbourXOffsets[7] = -1;
- neighbourZOffsets[0] = -1;
- neighbourZOffsets[1] = 0;
- neighbourZOffsets[2] = 1;
- neighbourZOffsets[3] = 0;
- neighbourZOffsets[4] = -1;
- neighbourZOffsets[5] = 1;
- neighbourZOffsets[6] = 1;
- neighbourZOffsets[7] = -1;
- }
- protected override IEnumerable<Progress> ScanInternal () {
- if (nodeSize <= 0) {
- yield break;
- }
-
- UpdateTransform();
- if (width > 1024 || depth > 1024) {
- Debug.LogError("One of the grid's sides is longer than 1024 nodes");
- yield break;
- }
- #if !ASTAR_JPS
- if (this.useJumpPointSearch) {
- Debug.LogError("Trying to use Jump Point Search, but support for it is not enabled. Please enable it in the inspector (Grid Graph settings).");
- }
- #endif
- SetUpOffsetsAndCosts();
-
- GridNode.SetGridGraph((int)graphIndex, this);
- yield return new Progress(0.05f, "Creating nodes");
-
- nodes = new GridNode[width*depth];
- for (int z = 0; z < depth; z++) {
- for (int x = 0; x < width; x++) {
- var index = z*width+x;
- var node = nodes[index] = new GridNode(active);
- node.GraphIndex = graphIndex;
- node.NodeInGridIndex = index;
- }
- }
-
- if (collision == null) {
- collision = new GraphCollision();
- }
- collision.Initialize(transform, nodeSize);
- textureData.Initialize();
- int progressCounter = 0;
- const int YieldEveryNNodes = 1000;
- for (int z = 0; z < depth; z++) {
-
- if (progressCounter >= YieldEveryNNodes) {
- progressCounter = 0;
- yield return new Progress(Mathf.Lerp(0.1f, 0.7f, z/(float)depth), "Calculating positions");
- }
- progressCounter += width;
- for (int x = 0; x < width; x++) {
-
-
- RecalculateCell(x, z);
-
- textureData.Apply(nodes[z*width + x] as GridNode, x, z);
- }
- }
- progressCounter = 0;
- for (int z = 0; z < depth; z++) {
-
- if (progressCounter >= YieldEveryNNodes) {
- progressCounter = 0;
- yield return new Progress(Mathf.Lerp(0.7f, 0.9f, z/(float)depth), "Calculating connections");
- }
- progressCounter += width;
- for (int x = 0; x < width; x++) {
-
- CalculateConnections(x, z);
- }
- }
- yield return new Progress(0.95f, "Calculating erosion");
-
- ErodeWalkableArea();
- }
-
-
-
-
-
-
- [System.Obsolete("Use RecalculateCell instead which works both for grid graphs and layered grid graphs")]
- public virtual void UpdateNodePositionCollision (GridNode node, int x, int z, bool resetPenalty = true) {
- RecalculateCell(x, z, resetPenalty, false);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public virtual void RecalculateCell (int x, int z, bool resetPenalties = true, bool resetTags = true) {
- var node = nodes[z*width + x];
-
- node.position = GraphPointToWorld(x, z, 0);
- RaycastHit hit;
- bool walkable;
-
-
- Vector3 position = collision.CheckHeight((Vector3)node.position, out hit, out walkable);
- node.position = (Int3)position;
- if (resetPenalties) {
- node.Penalty = initialPenalty;
-
- if (penaltyPosition) {
- node.Penalty += (uint)Mathf.RoundToInt((node.position.y-penaltyPositionOffset)*penaltyPositionFactor);
- }
- }
- if (resetTags) {
- node.Tag = 0;
- }
-
- if (walkable && useRaycastNormal && collision.heightCheck) {
- if (hit.normal != Vector3.zero) {
-
- float angle = Vector3.Dot(hit.normal.normalized, collision.up);
-
- if (penaltyAngle && resetPenalties) {
- node.Penalty += (uint)Mathf.RoundToInt((1F-Mathf.Pow(angle, penaltyAnglePower))*penaltyAngleFactor);
- }
-
- float cosAngle = Mathf.Cos(maxSlope*Mathf.Deg2Rad);
-
- if (angle < cosAngle) {
- walkable = false;
- }
- }
- }
-
-
- node.Walkable = walkable && collision.Check((Vector3)node.position);
-
- node.WalkableErosion = node.Walkable;
- }
-
-
-
-
-
-
-
- protected virtual bool ErosionAnyFalseConnections (GraphNode baseNode) {
- var node = baseNode as GridNode;
- if (neighbours == NumNeighbours.Six) {
-
- for (int i = 0; i < 6; i++) {
- if (!node.HasConnectionInDirection(hexagonNeighbourIndices[i])) {
- return true;
- }
- }
- } else {
-
- for (int i = 0; i < 4; i++) {
- if (!node.HasConnectionInDirection(i)) {
- return true;
- }
- }
- }
- return false;
- }
-
- void ErodeNode (GraphNode node) {
- if (node.Walkable && ErosionAnyFalseConnections(node)) {
- node.Walkable = false;
- }
- }
-
- void ErodeNodeWithTagsInit (GraphNode node) {
- if (node.Walkable && ErosionAnyFalseConnections(node)) {
- node.Tag = (uint)erosionFirstTag;
- } else {
- node.Tag = 0;
- }
- }
-
- void ErodeNodeWithTags (GraphNode node, int iteration) {
- var gnode = node as GridNodeBase;
- if (gnode.Walkable && gnode.Tag >= erosionFirstTag && gnode.Tag < erosionFirstTag + iteration) {
- if (neighbours == NumNeighbours.Six) {
-
- for (int i = 0; i < 6; i++) {
- var other = gnode.GetNeighbourAlongDirection(hexagonNeighbourIndices[i]);
- if (other != null) {
- uint tag = other.Tag;
- if (tag > erosionFirstTag + iteration || tag < erosionFirstTag) {
- other.Tag = (uint)(erosionFirstTag+iteration);
- }
- }
- }
- } else {
-
- for (int i = 0; i < 4; i++) {
- var other = gnode.GetNeighbourAlongDirection(i);
- if (other != null) {
- uint tag = other.Tag;
- if (tag > erosionFirstTag + iteration || tag < erosionFirstTag) {
- other.Tag = (uint)(erosionFirstTag+iteration);
- }
- }
- }
- }
- }
- }
-
-
-
-
- public virtual void ErodeWalkableArea () {
- ErodeWalkableArea(0, 0, Width, Depth);
- }
-
-
-
-
-
-
-
-
- public void ErodeWalkableArea (int xmin, int zmin, int xmax, int zmax) {
- if (erosionUseTags) {
- if (erodeIterations+erosionFirstTag > 31) {
- Debug.LogError("Too few tags available for "+erodeIterations+" erode iterations and starting with tag " + erosionFirstTag + " (erodeIterations+erosionFirstTag > 31)", active);
- return;
- }
- if (erosionFirstTag <= 0) {
- Debug.LogError("First erosion tag must be greater or equal to 1", active);
- return;
- }
- }
- if (erodeIterations == 0) return;
-
- var rect = new IntRect(xmin, zmin, xmax - 1, zmax - 1);
- var nodesInRect = GetNodesInRegion(rect);
- int nodeCount = nodesInRect.Count;
- for (int it = 0; it < erodeIterations; it++) {
- if (erosionUseTags) {
- if (it == 0) {
- for (int i = 0; i < nodeCount; i++) {
- ErodeNodeWithTagsInit(nodesInRect[i]);
- }
- } else {
- for (int i = 0; i < nodeCount; i++) {
- ErodeNodeWithTags(nodesInRect[i], it);
- }
- }
- } else {
-
-
- for (int i = 0; i < nodeCount; i++) {
- ErodeNode(nodesInRect[i]);
- }
- for (int i = 0; i < nodeCount; i++) {
- CalculateConnections(nodesInRect[i] as GridNodeBase);
- }
- }
- }
-
- Pathfinding.Util.ListPool<GraphNode>.Release(ref nodesInRect);
- }
-
-
-
-
-
-
-
-
-
-
-
- public virtual bool IsValidConnection (GridNodeBase node1, GridNodeBase node2) {
- if (!node1.Walkable || !node2.Walkable) {
- return false;
- }
- if (maxClimb <= 0 || collision.use2D) return true;
- if (transform.onlyTranslational) {
-
-
-
-
- return System.Math.Abs(node1.position.y - node2.position.y) <= maxClimb*Int3.Precision;
- } else {
- var p1 = (Vector3)node1.position;
- var p2 = (Vector3)node2.position;
- var up = transform.WorldUpAtGraphPosition(p1);
- return System.Math.Abs(Vector3.Dot(up, p1) - Vector3.Dot(up, p2)) <= maxClimb;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public void CalculateConnectionsForCellAndNeighbours (int x, int z) {
- CalculateConnections(x, z);
- for (int i = 0; i < 8; i++) {
- int nx = x + neighbourXOffsets[i];
- int nz = z + neighbourZOffsets[i];
-
-
-
- if (nx >= 0 & nz >= 0 & nx < width & nz < depth) {
- CalculateConnections(nx, nz);
- }
- }
- }
-
-
-
-
- [System.Obsolete("Use the instance function instead")]
- public static void CalculateConnections (GridNode node) {
- (AstarData.GetGraph(node) as GridGraph).CalculateConnections((GridNodeBase)node);
- }
-
-
-
-
-
-
- public virtual void CalculateConnections (GridNodeBase node) {
- int index = node.NodeInGridIndex;
- int x = index % width;
- int z = index / width;
- CalculateConnections(x, z);
- }
-
-
-
-
- [System.Obsolete("Use CalculateConnections(x,z) or CalculateConnections(node) instead")]
- public virtual void CalculateConnections (int x, int z, GridNode node) {
- CalculateConnections(x, z);
- }
-
-
-
-
-
-
-
-
-
-
- public virtual void CalculateConnections (int x, int z) {
- var node = nodes[z*width + x] as GridNode;
-
- if (!node.Walkable) {
-
-
- node.ResetConnectionsInternal();
- return;
- }
-
- int index = node.NodeInGridIndex;
- if (neighbours == NumNeighbours.Four || neighbours == NumNeighbours.Eight) {
-
-
-
- int conns = 0;
-
- for (int i = 0; i < 4; i++) {
- int nx = x + neighbourXOffsets[i];
- int nz = z + neighbourZOffsets[i];
-
-
-
- if (nx >= 0 & nz >= 0 & nx < width & nz < depth) {
- var other = nodes[index+neighbourOffsets[i]];
- if (IsValidConnection(node, other)) {
-
- conns |= 1 << i;
- }
- }
- }
-
- int diagConns = 0;
-
- if (neighbours == NumNeighbours.Eight) {
- if (cutCorners) {
- for (int i = 0; i < 4; i++) {
-
-
-
-
-
-
-
-
- if (((conns >> i | conns >> (i+1) | conns >> (i+1-4)) & 1) != 0) {
- int directionIndex = i+4;
- int nx = x + neighbourXOffsets[directionIndex];
- int nz = z + neighbourZOffsets[directionIndex];
- if (nx >= 0 & nz >= 0 & nx < width & nz < depth) {
- GridNodeBase other = nodes[index+neighbourOffsets[directionIndex]];
- if (IsValidConnection(node, other)) {
- diagConns |= 1 << directionIndex;
- }
- }
- }
- }
- } else {
- for (int i = 0; i < 4; i++) {
-
-
-
-
- if ((conns >> i & 1) != 0 && ((conns >> (i+1) | conns >> (i+1-4)) & 1) != 0) {
- GridNodeBase other = nodes[index+neighbourOffsets[i+4]];
- if (IsValidConnection(node, other)) {
- diagConns |= 1 << (i+4);
- }
- }
- }
- }
- }
-
- node.SetAllConnectionInternal(conns | diagConns);
- } else {
-
-
-
- node.ResetConnectionsInternal();
-
- for (int j = 0; j < hexagonNeighbourIndices.Length; j++) {
- var i = hexagonNeighbourIndices[j];
- int nx = x + neighbourXOffsets[i];
- int nz = z + neighbourZOffsets[i];
- if (nx >= 0 & nz >= 0 & nx < width & nz < depth) {
- var other = nodes[index+neighbourOffsets[i]];
- node.SetConnectionInternal(i, IsValidConnection(node, other));
- }
- }
- }
- }
- public override void OnDrawGizmos (RetainedGizmos gizmos, bool drawNodes) {
- using (var helper = gizmos.GetSingleFrameGizmoHelper(active)) {
-
-
- int w, d;
- float s;
- CalculateDimensions(out w, out d, out s);
- var bounds = new Bounds();
- bounds.SetMinMax(Vector3.zero, new Vector3(w, 0, d));
- var trans = CalculateTransform();
- helper.builder.DrawWireCube(trans, bounds, Color.white);
- int nodeCount = nodes != null ? nodes.Length : -1;
- if (this is LayerGridGraph) nodeCount = (this as LayerGridGraph).nodes != null ? (this as LayerGridGraph).nodes.Length : -1;
- if (drawNodes && width*depth*LayerCount != nodeCount) {
- var color = new Color(1, 1, 1, 0.2f);
- for (int z = 0; z < d; z++) {
- helper.builder.DrawLine(trans.Transform(new Vector3(0, 0, z)), trans.Transform(new Vector3(w, 0, z)), color);
- }
- for (int x = 0; x < w; x++) {
- helper.builder.DrawLine(trans.Transform(new Vector3(x, 0, 0)), trans.Transform(new Vector3(x, 0, d)), color);
- }
- }
- }
- if (!drawNodes) {
- return;
- }
-
-
-
-
- const int chunkWidth = 32;
- GridNodeBase[] allNodes = ArrayPool<GridNodeBase>.Claim(chunkWidth*chunkWidth*LayerCount);
- for (int cx = width/chunkWidth; cx >= 0; cx--) {
- for (int cz = depth/chunkWidth; cz >= 0; cz--) {
- Profiler.BeginSample("Hash");
- var allNodesCount = GetNodesInRegion(new IntRect(cx*chunkWidth, cz*chunkWidth, (cx+1)*chunkWidth - 1, (cz+1)*chunkWidth - 1), allNodes);
- var hasher = new RetainedGizmos.Hasher(active);
- hasher.AddHash(showMeshOutline ? 1 : 0);
- hasher.AddHash(showMeshSurface ? 1 : 0);
- hasher.AddHash(showNodeConnections ? 1 : 0);
- for (int i = 0; i < allNodesCount; i++) {
- hasher.HashNode(allNodes[i]);
- }
- Profiler.EndSample();
- if (!gizmos.Draw(hasher)) {
- Profiler.BeginSample("Rebuild Retained Gizmo Chunk");
- using (var helper = gizmos.GetGizmoHelper(active, hasher)) {
- if (showNodeConnections) {
- for (int i = 0; i < allNodesCount; i++) {
-
- if (allNodes[i].Walkable) {
- helper.DrawConnections(allNodes[i]);
- }
- }
- }
- if (showMeshSurface || showMeshOutline) CreateNavmeshSurfaceVisualization(allNodes, allNodesCount, helper);
- }
- Profiler.EndSample();
- }
- }
- }
- ArrayPool<GridNodeBase>.Release(ref allNodes);
- if (active.showUnwalkableNodes) DrawUnwalkableNodes(nodeSize * 0.3f);
- }
-
-
-
-
- void CreateNavmeshSurfaceVisualization (GridNodeBase[] nodes, int nodeCount, GraphGizmoHelper helper) {
-
- int walkable = 0;
- for (int i = 0; i < nodeCount; i++) {
- if (nodes[i].Walkable) walkable++;
- }
- var neighbourIndices = neighbours == NumNeighbours.Six ? hexagonNeighbourIndices : new [] { 0, 1, 2, 3 };
- var offsetMultiplier = neighbours == NumNeighbours.Six ? 0.333333f : 0.5f;
-
- var trianglesPerNode = neighbourIndices.Length-2;
- var verticesPerNode = 3*trianglesPerNode;
-
- var vertices = ArrayPool<Vector3>.Claim(walkable*verticesPerNode);
- var colors = ArrayPool<Color>.Claim(walkable*verticesPerNode);
- int baseIndex = 0;
- for (int i = 0; i < nodeCount; i++) {
- var node = nodes[i];
- if (!node.Walkable) continue;
- var nodeColor = helper.NodeColor(node);
-
- if (nodeColor.a <= 0.001f) continue;
- for (int dIndex = 0; dIndex < neighbourIndices.Length; dIndex++) {
-
-
-
-
-
-
- var d = neighbourIndices[dIndex];
- var nextD = neighbourIndices[(dIndex + 1) % neighbourIndices.Length];
- GridNodeBase n1, n2, n3 = null;
- n1 = node.GetNeighbourAlongDirection(d);
- if (n1 != null && neighbours != NumNeighbours.Six) {
- n3 = n1.GetNeighbourAlongDirection(nextD);
- }
- n2 = node.GetNeighbourAlongDirection(nextD);
- if (n2 != null && n3 == null && neighbours != NumNeighbours.Six) {
- n3 = n2.GetNeighbourAlongDirection(d);
- }
-
- Vector3 p = new Vector3(node.XCoordinateInGrid + 0.5f, 0, node.ZCoordinateInGrid + 0.5f);
-
- p.x += (neighbourXOffsets[d] + neighbourXOffsets[nextD]) * offsetMultiplier;
- p.z += (neighbourZOffsets[d] + neighbourZOffsets[nextD]) * offsetMultiplier;
-
- p.y += transform.InverseTransform((Vector3)node.position).y;
- if (n1 != null) p.y += transform.InverseTransform((Vector3)n1.position).y;
- if (n2 != null) p.y += transform.InverseTransform((Vector3)n2.position).y;
- if (n3 != null) p.y += transform.InverseTransform((Vector3)n3.position).y;
- p.y /= (1f + (n1 != null ? 1f : 0f) + (n2 != null ? 1f : 0f) + (n3 != null ? 1f : 0f));
-
-
- p = transform.Transform(p);
- vertices[baseIndex + dIndex] = p;
- }
- if (neighbours == NumNeighbours.Six) {
-
- vertices[baseIndex + 6] = vertices[baseIndex + 0];
- vertices[baseIndex + 7] = vertices[baseIndex + 2];
- vertices[baseIndex + 8] = vertices[baseIndex + 3];
- vertices[baseIndex + 9] = vertices[baseIndex + 0];
- vertices[baseIndex + 10] = vertices[baseIndex + 3];
- vertices[baseIndex + 11] = vertices[baseIndex + 5];
- } else {
-
- vertices[baseIndex + 4] = vertices[baseIndex + 0];
- vertices[baseIndex + 5] = vertices[baseIndex + 2];
- }
-
- for (int j = 0; j < verticesPerNode; j++) {
- colors[baseIndex + j] = nodeColor;
- }
-
- for (int j = 0; j < neighbourIndices.Length; j++) {
- var other = node.GetNeighbourAlongDirection(neighbourIndices[(j+1) % neighbourIndices.Length]);
-
-
-
-
-
- if (other == null || (showMeshOutline && node.NodeInGridIndex < other.NodeInGridIndex)) {
- helper.builder.DrawLine(vertices[baseIndex + j], vertices[baseIndex + (j+1) % neighbourIndices.Length], other == null ? Color.black : nodeColor);
- }
- }
- baseIndex += verticesPerNode;
- }
- if (showMeshSurface) helper.DrawTriangles(vertices, colors, baseIndex*trianglesPerNode/verticesPerNode);
- ArrayPool<Vector3>.Release(ref vertices);
- ArrayPool<Color>.Release(ref colors);
- }
-
-
-
-
-
-
-
- public IntRect GetRectFromBounds (Bounds bounds) {
-
-
-
- bounds = transform.InverseTransform(bounds);
- Vector3 min = bounds.min;
- Vector3 max = bounds.max;
- int minX = Mathf.RoundToInt(min.x-0.5F);
- int maxX = Mathf.RoundToInt(max.x-0.5F);
- int minZ = Mathf.RoundToInt(min.z-0.5F);
- int maxZ = Mathf.RoundToInt(max.z-0.5F);
- var originalRect = new IntRect(minX, minZ, maxX, maxZ);
-
- var gridRect = new IntRect(0, 0, width-1, depth-1);
-
- return IntRect.Intersection(originalRect, gridRect);
- }
-
- [System.Obsolete("This method has been renamed to GetNodesInRegion", true)]
- public List<GraphNode> GetNodesInArea (Bounds bounds) {
- return GetNodesInRegion(bounds);
- }
-
- [System.Obsolete("This method has been renamed to GetNodesInRegion", true)]
- public List<GraphNode> GetNodesInArea (GraphUpdateShape shape) {
- return GetNodesInRegion(shape);
- }
-
- [System.Obsolete("This method has been renamed to GetNodesInRegion", true)]
- public List<GraphNode> GetNodesInArea (Bounds bounds, GraphUpdateShape shape) {
- return GetNodesInRegion(bounds, shape);
- }
-
-
-
-
-
-
-
- public List<GraphNode> GetNodesInRegion (Bounds bounds) {
- return GetNodesInRegion(bounds, null);
- }
-
-
-
-
-
-
-
- public List<GraphNode> GetNodesInRegion (GraphUpdateShape shape) {
- return GetNodesInRegion(shape.GetBounds(), shape);
- }
-
-
-
-
-
- protected virtual List<GraphNode> GetNodesInRegion (Bounds bounds, GraphUpdateShape shape) {
- var rect = GetRectFromBounds(bounds);
- if (nodes == null || !rect.IsValid() || nodes.Length != width*depth) {
- return ListPool<GraphNode>.Claim();
- }
-
- var inArea = ListPool<GraphNode>.Claim(rect.Width*rect.Height);
-
- for (int x = rect.xmin; x <= rect.xmax; x++) {
- for (int z = rect.ymin; z <= rect.ymax; z++) {
- int index = z*width+x;
- GraphNode node = nodes[index];
-
-
- if (bounds.Contains((Vector3)node.position) && (shape == null || shape.Contains((Vector3)node.position))) {
- inArea.Add(node);
- }
- }
- }
- return inArea;
- }
-
-
-
-
-
-
- public virtual List<GraphNode> GetNodesInRegion (IntRect rect) {
-
-
- var gridRect = new IntRect(0, 0, width-1, depth-1);
- rect = IntRect.Intersection(rect, gridRect);
- if (nodes == null || !rect.IsValid() || nodes.Length != width*depth) return ListPool<GraphNode>.Claim(0);
-
- var inArea = ListPool<GraphNode>.Claim(rect.Width*rect.Height);
- for (int z = rect.ymin; z <= rect.ymax; z++) {
- var zw = z*Width;
- for (int x = rect.xmin; x <= rect.xmax; x++) {
- inArea.Add(nodes[zw + x]);
- }
- }
- return inArea;
- }
-
-
-
-
-
-
-
-
-
-
-
- public virtual int GetNodesInRegion (IntRect rect, GridNodeBase[] buffer) {
-
-
- var gridRect = new IntRect(0, 0, width-1, depth-1);
- rect = IntRect.Intersection(rect, gridRect);
- if (nodes == null || !rect.IsValid() || nodes.Length != width*depth) return 0;
- if (buffer.Length < rect.Width*rect.Height) throw new System.ArgumentException("Buffer is too small");
- int counter = 0;
- for (int z = rect.ymin; z <= rect.ymax; z++, counter += rect.Width) {
- System.Array.Copy(nodes, z*Width + rect.xmin, buffer, counter, rect.Width);
- }
- return counter;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public virtual GridNodeBase GetNode (int x, int z) {
- if (x < 0 || z < 0 || x >= width || z >= depth) return null;
- return nodes[x + z*width];
- }
- GraphUpdateThreading IUpdatableGraph.CanUpdateAsync (GraphUpdateObject o) {
- return GraphUpdateThreading.UnityThread;
- }
- void IUpdatableGraph.UpdateAreaInit (GraphUpdateObject o) {}
- void IUpdatableGraph.UpdateAreaPost (GraphUpdateObject o) {}
- protected void CalculateAffectedRegions (GraphUpdateObject o, out IntRect originalRect, out IntRect affectRect, out IntRect physicsRect, out bool willChangeWalkability, out int erosion) {
-
-
-
- var bounds = transform.InverseTransform(o.bounds);
- Vector3 min = bounds.min;
- Vector3 max = bounds.max;
- int minX = Mathf.RoundToInt(min.x-0.5F);
- int maxX = Mathf.RoundToInt(max.x-0.5F);
- int minZ = Mathf.RoundToInt(min.z-0.5F);
- int maxZ = Mathf.RoundToInt(max.z-0.5F);
-
- originalRect = new IntRect(minX, minZ, maxX, maxZ);
- affectRect = originalRect;
- physicsRect = originalRect;
- erosion = o.updateErosion ? erodeIterations : 0;
- willChangeWalkability = o.updatePhysics || o.modifyWalkability;
-
- if (o.updatePhysics && !o.modifyWalkability) {
-
- if (collision.collisionCheck) {
- Vector3 margin = new Vector3(collision.diameter, 0, collision.diameter)*0.5F;
- min -= margin*1.02F;
- max += margin*1.02F;
- physicsRect = new IntRect(
- Mathf.RoundToInt(min.x-0.5F),
- Mathf.RoundToInt(min.z-0.5F),
- Mathf.RoundToInt(max.x-0.5F),
- Mathf.RoundToInt(max.z-0.5F)
- );
- affectRect = IntRect.Union(physicsRect, affectRect);
- }
- }
- if (willChangeWalkability || erosion > 0) {
-
- affectRect = affectRect.Expand(erosion + 1);
- }
- }
-
- void IUpdatableGraph.UpdateArea (GraphUpdateObject o) {
- if (nodes == null || nodes.Length != width*depth) {
- Debug.LogWarning("The Grid Graph is not scanned, cannot update area");
-
- return;
- }
- IntRect originalRect, affectRect, physicsRect;
- bool willChangeWalkability;
- int erosion;
- CalculateAffectedRegions(o, out originalRect, out affectRect, out physicsRect, out willChangeWalkability, out erosion);
- #if ASTARDEBUG
- var debugMatrix = transform * Matrix4x4.TRS(new Vector3(0.5f, 0, 0.5f), Quaternion.identity, Vector3.one);
- originalRect.DebugDraw(debugMatrix, Color.red);
- #endif
-
- var gridRect = new IntRect(0, 0, width-1, depth-1);
-
- IntRect clampedRect = IntRect.Intersection(affectRect, gridRect);
-
- for (int z = clampedRect.ymin; z <= clampedRect.ymax; z++) {
- for (int x = clampedRect.xmin; x <= clampedRect.xmax; x++) {
- o.WillUpdateNode(nodes[z*width+x]);
- }
- }
-
- if (o.updatePhysics && !o.modifyWalkability) {
- collision.Initialize(transform, nodeSize);
- clampedRect = IntRect.Intersection(physicsRect, gridRect);
- for (int z = clampedRect.ymin; z <= clampedRect.ymax; z++) {
- for (int x = clampedRect.xmin; x <= clampedRect.xmax; x++) {
- RecalculateCell(x, z, o.resetPenaltyOnPhysics, false);
- }
- }
- }
-
- clampedRect = IntRect.Intersection(originalRect, gridRect);
- for (int z = clampedRect.ymin; z <= clampedRect.ymax; z++) {
- for (int x = clampedRect.xmin; x <= clampedRect.xmax; x++) {
- int index = z*width+x;
- GridNodeBase node = nodes[index];
- if (o.bounds.Contains((Vector3)node.position)) {
- if (willChangeWalkability) {
- node.Walkable = node.WalkableErosion;
- o.Apply(node);
- node.WalkableErosion = node.Walkable;
- } else {
- o.Apply(node);
- }
- }
- }
- }
- #if ASTARDEBUG
- physicsRect.DebugDraw(debugMatrix, Color.blue);
- affectRect.DebugDraw(debugMatrix, Color.black);
- #endif
-
- if (willChangeWalkability && erosion == 0) {
- clampedRect = IntRect.Intersection(affectRect, gridRect);
- for (int x = clampedRect.xmin; x <= clampedRect.xmax; x++) {
- for (int z = clampedRect.ymin; z <= clampedRect.ymax; z++) {
- CalculateConnections(x, z);
- }
- }
- } else if (willChangeWalkability && erosion > 0) {
- clampedRect = IntRect.Union(originalRect, physicsRect);
- IntRect erosionRect1 = clampedRect.Expand(erosion);
- IntRect erosionRect2 = erosionRect1.Expand(erosion);
- erosionRect1 = IntRect.Intersection(erosionRect1, gridRect);
- erosionRect2 = IntRect.Intersection(erosionRect2, gridRect);
- #if ASTARDEBUG
- erosionRect1.DebugDraw(debugMatrix, Color.magenta);
- erosionRect2.DebugDraw(debugMatrix, Color.cyan);
- #endif
-
-
-
-
- for (int x = erosionRect2.xmin; x <= erosionRect2.xmax; x++) {
- for (int z = erosionRect2.ymin; z <= erosionRect2.ymax; z++) {
- int index = z*width+x;
- GridNodeBase node = nodes[index];
- bool tmp = node.Walkable;
- node.Walkable = node.WalkableErosion;
- if (!erosionRect1.Contains(x, z)) {
-
- node.TmpWalkable = tmp;
- }
- }
- }
- for (int x = erosionRect2.xmin; x <= erosionRect2.xmax; x++) {
- for (int z = erosionRect2.ymin; z <= erosionRect2.ymax; z++) {
- CalculateConnections(x, z);
- }
- }
-
- ErodeWalkableArea(erosionRect2.xmin, erosionRect2.ymin, erosionRect2.xmax+1, erosionRect2.ymax+1);
- for (int x = erosionRect2.xmin; x <= erosionRect2.xmax; x++) {
- for (int z = erosionRect2.ymin; z <= erosionRect2.ymax; z++) {
- if (erosionRect1.Contains(x, z)) continue;
- int index = z*width+x;
- GridNodeBase node = nodes[index];
-
- node.Walkable = node.TmpWalkable;
- }
- }
-
- for (int x = erosionRect2.xmin; x <= erosionRect2.xmax; x++) {
- for (int z = erosionRect2.ymin; z <= erosionRect2.ymax; z++) {
- CalculateConnections(x, z);
- }
- }
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool Linecast (Vector3 from, Vector3 to) {
- GraphHitInfo hit;
- return Linecast(from, to, out hit);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("The hint parameter is deprecated")]
- public bool Linecast (Vector3 from, Vector3 to, GraphNode hint) {
- GraphHitInfo hit;
- return Linecast(from, to, hint, out hit);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("The hint parameter is deprecated")]
- public bool Linecast (Vector3 from, Vector3 to, GraphNode hint, out GraphHitInfo hit) {
- return Linecast(from, to, hint, out hit, null);
- }
-
- protected static long CrossMagnitude (Int2 a, Int2 b) {
- return (long)a.x*b.y - (long)b.x*a.y;
- }
-
-
-
-
-
-
-
- protected bool ClipLineSegmentToBounds (Vector3 a, Vector3 b, out Vector3 outA, out Vector3 outB) {
-
-
- if (a.x < 0 || a.z < 0 || a.x > width || a.z > depth ||
- b.x < 0 || b.z < 0 || b.x > width || b.z > depth) {
-
- var p1 = new Vector3(0, 0, 0);
- var p2 = new Vector3(0, 0, depth);
- var p3 = new Vector3(width, 0, depth);
- var p4 = new Vector3(width, 0, 0);
- int intersectCount = 0;
- bool intersect;
- Vector3 intersection;
- intersection = VectorMath.SegmentIntersectionPointXZ(a, b, p1, p2, out intersect);
- if (intersect) {
- intersectCount++;
- if (!VectorMath.RightOrColinearXZ(p1, p2, a)) {
- a = intersection;
- } else {
- b = intersection;
- }
- }
- intersection = VectorMath.SegmentIntersectionPointXZ(a, b, p2, p3, out intersect);
- if (intersect) {
- intersectCount++;
- if (!VectorMath.RightOrColinearXZ(p2, p3, a)) {
- a = intersection;
- } else {
- b = intersection;
- }
- }
- intersection = VectorMath.SegmentIntersectionPointXZ(a, b, p3, p4, out intersect);
- if (intersect) {
- intersectCount++;
- if (!VectorMath.RightOrColinearXZ(p3, p4, a)) {
- a = intersection;
- } else {
- b = intersection;
- }
- }
- intersection = VectorMath.SegmentIntersectionPointXZ(a, b, p4, p1, out intersect);
- if (intersect) {
- intersectCount++;
- if (!VectorMath.RightOrColinearXZ(p4, p1, a)) {
- a = intersection;
- } else {
- b = intersection;
- }
- }
- if (intersectCount == 0) {
-
- outA = Vector3.zero;
- outB = Vector3.zero;
- return false;
- }
- }
- outA = a;
- outB = b;
- return true;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("The hint parameter is deprecated")]
- public bool Linecast (Vector3 from, Vector3 to, GraphNode hint, out GraphHitInfo hit, List<GraphNode> trace) {
- return Linecast(from, to, out hit, trace, null);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool Linecast (Vector3 from, Vector3 to, out GraphHitInfo hit, List<GraphNode> trace = null, System.Func<GraphNode, bool> filter = null) {
- GridHitInfo gridHit;
- hit = new GraphHitInfo();
- var res = Linecast(from, to, out gridHit, trace, filter);
- hit.origin = from;
- hit.node = gridHit.node;
- if (res) {
-
-
-
- var ndir = gridHit.direction;
- if (ndir == -1 || gridHit.node == null) {
-
- hit.point = gridHit.node != null ? (Vector3)gridHit.node.position : from;
- hit.tangentOrigin = Vector3.zero;
- hit.tangent = Vector3.zero;
- } else {
- Vector3 fromInGraphSpace = transform.InverseTransform(from);
- Vector3 toInGraphSpace = transform.InverseTransform(to);
-
-
-
-
- var fromInGraphSpace2D = new Vector2(fromInGraphSpace.x - 0.5f, fromInGraphSpace.z - 0.5f);
- var toInGraphSpace2D = new Vector2(toInGraphSpace.x - 0.5f, toInGraphSpace.z - 0.5f);
-
- var d1 = new Vector2(neighbourXOffsets[ndir], neighbourZOffsets[ndir]);
- var d2 = new Vector2(neighbourXOffsets[(ndir-1+4) & 0x3], neighbourZOffsets[(ndir-1+4) & 0x3]);
- Vector2 lineDirection = new Vector2(neighbourXOffsets[(ndir+1) & 0x3], neighbourZOffsets[(ndir+1) & 0x3]);
- var p = new Vector2(gridHit.node.XCoordinateInGrid, gridHit.node.ZCoordinateInGrid);
- Vector2 lineOrigin = p + (d1 + d2) * 0.5f;
-
- var intersection = VectorMath.LineIntersectionPoint(lineOrigin, lineOrigin+lineDirection, fromInGraphSpace2D, toInGraphSpace2D);
- var currentNodePositionInGraphSpace = transform.InverseTransform((Vector3)gridHit.node.position);
-
- var intersection3D = new Vector3(intersection.x + 0.5f, currentNodePositionInGraphSpace.y, intersection.y + 0.5f);
- var lineOrigin3D = new Vector3(lineOrigin.x + 0.5f, currentNodePositionInGraphSpace.y, lineOrigin.y + 0.5f);
- hit.point = transform.Transform(intersection3D);
- hit.tangentOrigin = transform.Transform(lineOrigin3D);
- hit.tangent = transform.TransformVector(new Vector3(lineDirection.x, 0, lineDirection.y));
- }
- } else {
- hit = new GraphHitInfo();
- }
- return res;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [System.Obsolete("Use Linecast instead")]
- public bool SnappedLinecast (Vector3 from, Vector3 to, GraphNode hint, out GraphHitInfo hit) {
- return Linecast(
- (Vector3)GetNearest(from, null).node.position,
- (Vector3)GetNearest(to, null).node.position,
- hint,
- out hit
- );
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool Linecast (GridNodeBase fromNode, GridNodeBase toNode, System.Func<GraphNode, bool> filter = null) {
- GridHitInfo hit;
- return Linecast(fromNode, new Vector2(0.5f, 0.5f), toNode, new Vector2(0.5f, 0.5f), out hit, null, filter);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool Linecast (Vector3 from, Vector3 to, out GridHitInfo hit, List<GraphNode> trace = null, System.Func<GraphNode, bool> filter = null) {
- Vector3 fromInGraphSpace = transform.InverseTransform(from);
- Vector3 toInGraphSpace = transform.InverseTransform(to);
- Vector3 fromInGraphSpaceClipped, toInGraphSpaceClipped;
-
- if (!ClipLineSegmentToBounds(fromInGraphSpace, toInGraphSpace, out fromInGraphSpaceClipped, out toInGraphSpaceClipped)) {
-
-
- hit = new GridHitInfo {
- node = null,
- direction = -1,
- };
- return false;
- }
-
- if ((fromInGraphSpace - fromInGraphSpaceClipped).sqrMagnitude > 0.001f*0.001f) {
- hit = new GridHitInfo {
- node = null,
- direction = -1,
- };
- return true;
- }
- bool toIsOutsideGraph = (toInGraphSpace - toInGraphSpaceClipped).sqrMagnitude > 0.001f*0.001f;
-
- var startNode = GetNearestFromGraphSpace(fromInGraphSpaceClipped);
- var endNode = GetNearestFromGraphSpace(toInGraphSpaceClipped);
- if (startNode == null || endNode == null) {
- hit = new GridHitInfo {
- node = null,
- direction = -1,
- };
- return false;
- }
- return Linecast(
- startNode, new Vector2(fromInGraphSpaceClipped.x - startNode.XCoordinateInGrid, fromInGraphSpaceClipped.z - startNode.ZCoordinateInGrid),
- endNode, new Vector2(toInGraphSpaceClipped.x - endNode.XCoordinateInGrid, toInGraphSpaceClipped.z - endNode.ZCoordinateInGrid),
- out hit,
- trace,
- filter,
- toIsOutsideGraph
- );
- }
- const int FixedPrecisionScale = 1024;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- public bool Linecast (GridNodeBase fromNode, Vector2 normalizedFromPoint, GridNodeBase toNode, Vector2 normalizedToPoint, out GridHitInfo hit, List<GraphNode> trace = null, System.Func<GraphNode, bool> filter = null, bool continuePastEnd = false) {
- var fixedNormalizedFromPoint = new Int2((int)Mathf.Round(normalizedFromPoint.x*FixedPrecisionScale), (int)Mathf.Round(normalizedFromPoint.y*FixedPrecisionScale));
- var fixedNormalizedToPoint = new Int2((int)Mathf.Round(normalizedToPoint.x*FixedPrecisionScale), (int)Mathf.Round(normalizedToPoint.y*FixedPrecisionScale));
- return Linecast(fromNode, fixedNormalizedFromPoint, toNode, fixedNormalizedToPoint, out hit, trace, filter, continuePastEnd);
- }
-
-
-
-
- public bool Linecast (GridNodeBase fromNode, Int2 fixedNormalizedFromPoint, GridNodeBase toNode, Int2 fixedNormalizedToPoint, out GridHitInfo hit, List<GraphNode> trace = null, System.Func<GraphNode, bool> filter = null, bool continuePastEnd = false) {
-
- if (fixedNormalizedFromPoint.x < 0 || fixedNormalizedFromPoint.x > FixedPrecisionScale) throw new System.ArgumentOutOfRangeException("normalizedFromPoint must be between 0 and 1");
- if (fixedNormalizedToPoint.x < 0 || fixedNormalizedToPoint.x > FixedPrecisionScale) throw new System.ArgumentOutOfRangeException("normalizedToPoint must be between 0 and 1");
- if (fromNode == null) throw new System.ArgumentNullException("fromNode");
- if (toNode == null) throw new System.ArgumentNullException("toNode");
-
- if ((filter != null && !filter(fromNode)) || !fromNode.Walkable) {
- hit = new GridHitInfo {
- node = fromNode,
- direction = -1,
- };
- return true;
- }
- if (fromNode == toNode) {
-
- hit = new GridHitInfo {
- node = fromNode,
- direction = -1,
- };
- return false;
- }
- var fromGridCoords = new Int2(fromNode.XCoordinateInGrid, fromNode.ZCoordinateInGrid);
- var toGridCoords = new Int2(toNode.XCoordinateInGrid, toNode.ZCoordinateInGrid);
- var fixedFrom = new Int2(fromGridCoords.x*FixedPrecisionScale, fromGridCoords.y*FixedPrecisionScale) + fixedNormalizedFromPoint;
- var fixedTo = new Int2(toGridCoords.x*FixedPrecisionScale, toGridCoords.y*FixedPrecisionScale) + fixedNormalizedToPoint;
- var dir = fixedTo - fixedFrom;
- int remainingSteps = System.Math.Abs(fromGridCoords.x - toGridCoords.x) + System.Math.Abs(fromGridCoords.y - toGridCoords.y);
- if (continuePastEnd) remainingSteps = int.MaxValue;
-
-
-
-
- if (fixedFrom == fixedTo) remainingSteps = 0;
-
-
- int quadrant = 0;
-
-
-
-
-
-
-
-
-
- var dirBiased = dir;
- if (dirBiased.x == 0) dirBiased.x = System.Math.Sign(FixedPrecisionScale/2 - fixedNormalizedToPoint.x);
- if (dirBiased.y == 0) dirBiased.y = System.Math.Sign(FixedPrecisionScale/2 - fixedNormalizedToPoint.y);
- if (dirBiased.x <= 0 && dirBiased.y > 0) quadrant = 1;
- else if (dirBiased.x < 0 && dirBiased.y <= 0) quadrant = 2;
- else if (dirBiased.x >= 0 && dirBiased.y < 0) quadrant = 3;
-
-
-
- int directionToReduceError = (quadrant + 1) & 0x3;
-
- int directionToIncreaseError = (quadrant + 2) & 0x3;
-
-
-
-
-
-
-
- long primaryDirectionError = CrossMagnitude(dir,
- new Int2(
- neighbourXOffsets[directionToIncreaseError]+neighbourXOffsets[directionToReduceError],
- neighbourZOffsets[directionToIncreaseError]+neighbourZOffsets[directionToReduceError]
- )
- );
-
-
-
- Int2 offset = new Int2(FixedPrecisionScale/2, FixedPrecisionScale/2) - fixedNormalizedFromPoint;
-
- long error = CrossMagnitude(dir, offset) * 2 / FixedPrecisionScale;
-
-
- long xerror = -dir.y * 2;
-
- long zerror = dir.x * 2;
-
-
-
-
-
-
-
-
-
-
-
-
- int symmetryBreakingDirection1 = directionToIncreaseError;
- int symmetryBreakingDirection2 = directionToReduceError;
- var fixedCenterOfToNode = new Int2(toGridCoords.x*FixedPrecisionScale, toGridCoords.y*FixedPrecisionScale) + new Int2(FixedPrecisionScale/2, FixedPrecisionScale/2);
- long targetNodeError = CrossMagnitude(dir, fixedCenterOfToNode - fixedFrom);
- if (targetNodeError < 0) {
- symmetryBreakingDirection1 = directionToReduceError;
- symmetryBreakingDirection2 = directionToIncreaseError;
- }
- GridNodeBase prevNode = null;
- GridNodeBase preventBacktrackingTo = null;
- for (; remainingSteps > 0; remainingSteps--) {
- if (trace != null) trace.Add(fromNode);
-
-
-
-
-
- var nerror = error + primaryDirectionError;
- int ndir;
- GridNodeBase nextNode;
- if (nerror == 0) {
-
-
-
- ndir = symmetryBreakingDirection1;
- nextNode = fromNode.GetNeighbourAlongDirection(ndir);
- if ((filter != null && nextNode != null && !filter(nextNode)) || nextNode == prevNode) nextNode = null;
- if (nextNode == null) {
-
- ndir = symmetryBreakingDirection2;
- nextNode = fromNode.GetNeighbourAlongDirection(ndir);
- if ((filter != null && nextNode != null && !filter(nextNode)) || nextNode == prevNode) nextNode = null;
- }
- } else {
-
-
-
- ndir = nerror < 0 ? directionToIncreaseError : directionToReduceError;
- nextNode = fromNode.GetNeighbourAlongDirection(ndir);
-
- if ((filter != null && nextNode != null && !filter(nextNode)) || nextNode == prevNode) nextNode = null;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- if (nextNode == null) {
-
- for (int i = -1; i <= 1; i += 2) {
- var d = (ndir + i + 4) & 0x3;
- if (error + xerror/2 * (neighbourXOffsets[ndir] + neighbourXOffsets[d]) + zerror/2 * (neighbourZOffsets[ndir]+neighbourZOffsets[d]) == 0) {
-
-
- nextNode = fromNode.GetNeighbourAlongDirection(d);
- if ((filter != null && nextNode != null && !filter(nextNode)) || nextNode == prevNode || nextNode == preventBacktrackingTo) nextNode = null;
- if (nextNode != null) {
-
-
- remainingSteps = 1 + System.Math.Abs(nextNode.XCoordinateInGrid - toGridCoords.x) + System.Math.Abs(nextNode.ZCoordinateInGrid - toGridCoords.y);
- ndir = d;
- prevNode = fromNode;
- preventBacktrackingTo = nextNode;
- }
- break;
- }
- }
-
- if (nextNode == null) {
- hit = new GridHitInfo {
- node = fromNode,
- direction = ndir,
- };
- return true;
- }
- }
-
- error += xerror * neighbourXOffsets[ndir] + zerror * neighbourZOffsets[ndir];
- fromNode = nextNode;
- }
- hit = new GridHitInfo {
- node = fromNode,
- direction = -1,
- };
- if (fromNode != toNode) {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- var dirToDestination = fixedTo - (new Int2(fromNode.XCoordinateInGrid*FixedPrecisionScale, fromNode.ZCoordinateInGrid*FixedPrecisionScale) + new Int2(FixedPrecisionScale/2, FixedPrecisionScale/2));
-
- if (Mathf.Abs(dirToDestination.x) == FixedPrecisionScale/2 && Mathf.Abs(dirToDestination.y) == FixedPrecisionScale/2) {
- var delta = new Int2(dirToDestination.x*2/FixedPrecisionScale, dirToDestination.y*2/FixedPrecisionScale);
-
-
-
-
-
-
-
-
-
-
-
-
- var counterClockwiseDirection = -1;
- for (int i = 0; i < 4; i++) {
-
- if (neighbourXOffsets[i]+neighbourXOffsets[(i+1)&0x3] == delta.x && neighbourZOffsets[i] + neighbourZOffsets[(i+1)&0x3] == delta.y) {
- counterClockwiseDirection = i;
- break;
- }
- }
- int traceLength = trace != null ? trace.Count : 0;
- int d = counterClockwiseDirection;
- var node = fromNode;
- for (int i = 0; i < 3 && node != toNode; i++) {
- if (trace != null) trace.Add(node);
- var prev = node;
- node = node.GetNeighbourAlongDirection(d);
- if (node == null || (filter != null && !filter(node))) {
- node = null;
- break;
- }
- d = (d + 1) & 0x3;
- }
- if (node != toNode) {
- if (trace != null) trace.RemoveRange(traceLength, trace.Count - traceLength);
- node = fromNode;
-
- d = (counterClockwiseDirection + 1) & 0x3;
- for (int i = 0; i < 3 && node != toNode; i++) {
- if (trace != null) trace.Add(node);
- var prev = node;
- node = node.GetNeighbourAlongDirection(d);
- if (node == null || (filter != null && !filter(node))) {
- node = null;
- break;
- }
- d = (d - 1 + 4) & 0x3;
- }
- if (node != toNode && trace != null) {
- trace.RemoveRange(traceLength, trace.Count - traceLength);
- }
- }
- fromNode = node;
- }
- }
- if (trace != null) trace.Add(fromNode);
- return fromNode != toNode;
- }
-
-
-
-
-
-
-
- public bool CheckConnection (GridNode node, int dir) {
- if (neighbours == NumNeighbours.Eight || neighbours == NumNeighbours.Six || dir < 4) {
- return node.HasConnectionInDirection(dir);
- } else {
- int dir1 = (dir-4-1) & 0x3;
- int dir2 = (dir-4+1) & 0x3;
- if (!node.HasConnectionInDirection(dir1) || !node.HasConnectionInDirection(dir2)) {
- return false;
- } else {
- GridNodeBase n1 = nodes[node.NodeInGridIndex+neighbourOffsets[dir1]];
- GridNodeBase n2 = nodes[node.NodeInGridIndex+neighbourOffsets[dir2]];
- if (!n1.Walkable || !n2.Walkable) {
- return false;
- }
- if (!n2.HasConnectionInDirection(dir1) || !n1.HasConnectionInDirection(dir2)) {
- return false;
- }
- }
- return true;
- }
- }
- protected override void SerializeExtraInfo (GraphSerializationContext ctx) {
- if (nodes == null) {
- ctx.writer.Write(-1);
- return;
- }
- ctx.writer.Write(nodes.Length);
- for (int i = 0; i < nodes.Length; i++) {
- nodes[i].SerializeNode(ctx);
- }
- }
- protected override void DeserializeExtraInfo (GraphSerializationContext ctx) {
- int count = ctx.reader.ReadInt32();
- if (count == -1) {
- nodes = null;
- return;
- }
- nodes = new GridNode[count];
- for (int i = 0; i < nodes.Length; i++) {
- nodes[i] = new GridNode(active);
- nodes[i].DeserializeNode(ctx);
- }
- }
- protected override void DeserializeSettingsCompatibility (GraphSerializationContext ctx) {
- base.DeserializeSettingsCompatibility(ctx);
- aspectRatio = ctx.reader.ReadSingle();
- rotation = ctx.DeserializeVector3();
- center = ctx.DeserializeVector3();
- unclampedSize = (Vector2)ctx.DeserializeVector3();
- nodeSize = ctx.reader.ReadSingle();
- collision.DeserializeSettingsCompatibility(ctx);
- maxClimb = ctx.reader.ReadSingle();
- ctx.reader.ReadInt32();
- maxSlope = ctx.reader.ReadSingle();
- erodeIterations = ctx.reader.ReadInt32();
- erosionUseTags = ctx.reader.ReadBoolean();
- erosionFirstTag = ctx.reader.ReadInt32();
- ctx.reader.ReadBoolean();
- neighbours = (NumNeighbours)ctx.reader.ReadInt32();
- cutCorners = ctx.reader.ReadBoolean();
- penaltyPosition = ctx.reader.ReadBoolean();
- penaltyPositionFactor = ctx.reader.ReadSingle();
- penaltyAngle = ctx.reader.ReadBoolean();
- penaltyAngleFactor = ctx.reader.ReadSingle();
- penaltyAnglePower = ctx.reader.ReadSingle();
- isometricAngle = ctx.reader.ReadSingle();
- uniformEdgeCosts = ctx.reader.ReadBoolean();
- useJumpPointSearch = ctx.reader.ReadBoolean();
- }
- protected override void PostDeserialization (GraphSerializationContext ctx) {
- UpdateTransform();
- SetUpOffsetsAndCosts();
- GridNode.SetGridGraph((int)graphIndex, this);
- if (nodes == null || nodes.Length == 0) return;
- if (width*depth != nodes.Length) {
- Debug.LogError("Node data did not match with bounds data. Probably a change to the bounds/width/depth data was made after scanning the graph just prior to saving it. Nodes will be discarded");
- nodes = new GridNode[0];
- return;
- }
- for (int z = 0; z < depth; z++) {
- for (int x = 0; x < width; x++) {
- var node = nodes[z*width+x];
- if (node == null) {
- Debug.LogError("Deserialization Error : Couldn't cast the node to the appropriate type - GridGenerator");
- return;
- }
- node.NodeInGridIndex = z*width+x;
- }
- }
- }
- }
-
-
-
-
- public enum NumNeighbours {
- Four,
- Eight,
- Six
- }
-
- public struct GridHitInfo {
-
-
-
-
- public GridNodeBase node;
-
-
-
-
-
-
- public int direction;
- }
- }
|