/// <summary> /// Lights up cells visible from the current position. Clear all lighting before calling. /// </summary> /// <param name="grid">The cell grid definition.</param> /// <param name="gridPosn">The player's position within the grid.</param> /// <param name="viewRadius">Maximum view distance; can be a fractional value.</param> public static List<ObjTile> ComputeVisibility(ObjMap bitMap, Vector2 gridPosn, float viewRadius) { //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //Сделать что-то с системой затенения, без помощи листа со всеми обсвещенными клетками //Сейчас кажется не такой плохой идеей, это можно еще использовать как все объекты, видимые персонажу //И как-нибудь их обрабатывать lightenedArea = new List<ObjTile>(); //Debug.Assert(gridPosn.x >= 0 && gridPosn.x < grid.xDim); //Debug.Assert(gridPosn.y >= 0 && gridPosn.y < grid.yDim); // Viewer's cell is always visible. bitMap.castLight((int)gridPosn.x, (int)gridPosn.y); //ATTENTION. Adds a tile with all objects in it, not only one object which was hit by light lightenedArea.Add(bitMap.getObject((int)gridPosn.x, (int)gridPosn.y)); // Cast light into cells for each of 8 octants. // // The left/right inverse slope values are initially 1 and 0, indicating a diagonal // and a horizontal line. These aren't strictly correct, as the view area is supposed // to be based on corners, not center points. We only really care about one side of the // wall at the edges of the octant though. // // NOTE: depending on the compiler, it's possible that passing the octant transform // values as four integers rather than an object reference would speed things up. // It's much tidier this way though. for (int txidx = 0; txidx < s_octantTransform.Length; txidx++) { CastLight(bitMap, gridPosn, viewRadius, 1, 1.0f, 0.0f, s_octantTransform[txidx]); } return lightenedArea; }
private List <Conflict> FindConflictsWithinSelectionSet( Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames, PairSet comparedFragmentPairs, INamedType parentType, SelectionSet selectionSet) { var conflicts = new List <Conflict>(); var cachedField = GetFieldsAndFragmentNames( cachedFieldsAndFragmentNames, parentType, selectionSet); var fieldMap = cachedField.NodeAndDef; var fragmentNames = cachedField.Names; CollectConflictsWithin( conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, fieldMap); if (fragmentNames.Count != 0) { // (B) Then collect conflicts between these fields and those represented by // each spread fragment name found. var comparedFragments = new ObjMap <bool>(); for (var i = 0; i < fragmentNames.Count; i++) { CollectConflictsBetweenFieldsAndFragment( conflicts, cachedFieldsAndFragmentNames, comparedFragments, comparedFragmentPairs, false, fieldMap, fragmentNames[i]); // (C) Then compare this fragment with all other fragments found in this // selection set to collect conflicts between fragments spread together. // This compares each item in the list of fragment names to every other // item in that same list (except for itself). for (var j = i + 1; j < fragmentNames.Count; j++) { CollectConflictsBetweenFragments( conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, false, fragmentNames[i], fragmentNames[j]); } } } return(conflicts); }
void OnDrawGizmos() { if (BoardManager.instance != null) if (BoardManager.instance.dun.objMap != null) bitMap = BoardManager.instance.dun.objMap; UnityEditor.Handles.color = new Color(0, 0, 255); if (bitMap != null) for (int i = 0; i <= BoardManager.instance.mapWidth; i++) for (int j = 0; j <= BoardManager.instance.mapHeight; j++) UnityEditor.Handles.Label(new Vector3(i, j + 0.05f, 0), bitMap.getID(i,j).ToString()); }
private void PairSetAdd(string a, string b, bool areMutuallyExclusive) { _data.TryGetValue(a, out var map); if (map == null) { map = new ObjMap <bool>(); _data[a] = map; } map[b] = areMutuallyExclusive; }
public override IEnumerable <Object> Init(object target) { var targetObj = target as Object; // generate the dependency graph for this target var rootGOgraph = ObjectGraphUtil.GetDependencyGraph(targetObj, new Object[0]); // merge it with the existing graphs (of other targets) graph = ObjectGraphUtil.MergeGraphs(graph, rootGOgraph); System.GC.Collect(); // targets have probably been substituted by cycleReps in the graph, so just use all parent-less nodes as seeds return(ObjectGraphUtil.GetRoots(rootGOgraph)); }
public static ObjNodeGraph GetActiveSceneReferenceGraph(HashSet <Object> targets) { var rootGameObjects = ActiveSceneRootGameObjects(); // build the Object graph var objGraph = new ObjMap(); var targetArray = targets.ToArray(); foreach (var rootGO in rootGameObjects) { var rootGOgraph = ObjectGraphUtil.GetDependencyGraph(rootGO, targetArray); objGraph = ObjectGraphUtil.MergeGraphs(objGraph, rootGOgraph); } // convert it to a SceneObjectNode graph, so we can destroy the objects return(ObjectGraphToObjectNodeGraph(objGraph, obj => GetActiveSceneObjectNode(obj, targets))); }
public WrenVM() { MethodNames = new List <string>(); ObjString name = new ObjString("core"); // Implicitly create a "core" module for the built in libraries. ObjModule coreModule = new ObjModule(name); _modules = new ObjMap(); _modules.Set(Obj.Null, coreModule); CoreLibrary core = new CoreLibrary(this); core.InitializeCore(); // Load in System functions Meta.LoadLibrary(this); }
// turn object graph into VisualNode graph (mapping obj -> name) static ObjNodeGraph ObjectGraphToObjectNodeGraph(ObjMap objGraph, System.Func <Object, ObjectNode> getNode) { var referencedObjects = objGraph.Values.SelectMany(o => o).ToHashSet(); // get all graph objects var allObjs = objGraph.Keys.Concat(referencedObjects).ToHashSet(); // map them to VisualNodes var objToNode = allObjs.ToDictionary(obj => obj, obj => getNode(obj)); // convert from Object to SceneObjectNode and flip the edge direction return(referencedObjects.ToDictionary( x => objToNode[x], x => objGraph .Where(pair => pair.Value.Contains(x)) .Select(pair => objToNode[pair.Key]) .ToHashSet() )); }
// merges graphs a and b. treat cycleRep objects with equal members as identical public static ObjMap MergeGraphs(ObjMap a, ObjMap b) { var aReps = a.Keys.OfType <CycleRep>(); var bReps = b.Keys.OfType <CycleRep>(); // find matching cycle reps var matches = new Dictionary <Object, Object>(); foreach (var ar in aReps) { foreach (var br in bReps) { if (ar.EqualMembers(br)) { matches[ar] = br; break; } } } System.Func <Object, Object> substitute = x => matches.ContainsKey(x) ? matches[x] : x; var result = b.ToDictionary(pair => pair.Key, pair => pair.Value); foreach (var x in a.Keys) { var addKey = substitute(x); var addValues = a[x].Select(v => substitute(v)); if (!result.ContainsKey(addKey)) { result[addKey] = new HashSet <Object>(); } foreach (var v in addValues) { result[addKey].Add(v); } } return(result); }
public WrenVM(Action <string> write, Action <string> error) { Write = write ?? (_ => Console.WriteLine(_)); Error = error ?? (_ => Console.Error.WriteLine(_)); MethodNames = new List <string>(); ObjString name = new ObjString("core"); // Implicitly create a "core" module for the built in libraries. ObjModule coreModule = new ObjModule(name); _modules = new ObjMap(); _modules.Set(Obj.Null, coreModule); CoreLibrary core = new CoreLibrary(this); core.InitializeCore(); // Load in System functions Meta.LoadLibrary(this); }
public static ObjNodeGraph GetReferenceGraph(string sceneFilePath, HashSet <Object> targets) { // get the scene's objects var sceneObjects = UnityEditorInternal .InternalEditorUtility .LoadSerializedFileAndForget(sceneFilePath) .ToHashSet(); // get the root gameObjects var rootGOs = sceneObjects .OfType <GameObject>() .Where(go => go.transform.parent == null); // build the Object graph var objGraph = new ObjMap(); var targetArray = targets.ToArray(); foreach (var rootGO in rootGOs) { var rootGOgraph = ObjectGraphUtil.GetDependencyGraph(rootGO, targetArray); objGraph = ObjectGraphUtil.MergeGraphs(objGraph, rootGOgraph); } // convert it to a SceneObjectNode graph, so we can destroy the objects var nodeGraph = ObjectGraphToObjectNodeGraph(objGraph, obj => GetSceneObjectNode(obj, targets, sceneObjects, sceneFilePath)); // destroy the scene Objects var sceneObjArray = sceneObjects.ToArray(); for (int i = 0; i < sceneObjArray.Length; i++) { Object.DestroyImmediate(sceneObjArray[i]); } System.GC.Collect(); return(nodeGraph); }
public override void Awake(GetAPI getAPI) { graph = new ObjMap(); base.Awake(getAPI); }
public PairSet() { _data = new ObjMap <ObjMap <bool> >(); }
private void CollectConflictsBetweenFieldsAndFragment( ValidationContext context, List <Conflict> conflicts, Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames, ObjMap <bool> comparedFragments, PairSet comparedFragmentPairs, bool areMutuallyExclusive, Dictionary <string, List <FieldDefPair> > fieldMap, string fragmentName) { // Memoize so a fragment is not compared for conflicts more than once. if (comparedFragments.ContainsKey(fragmentName)) { return; } comparedFragments[fragmentName] = true; FragmentDefinition fragment = context.GetFragment(fragmentName); if (fragment == null) { return; } var cachedField = GetReferencedFieldsAndFragmentNames( context, cachedFieldsAndFragmentNames, fragment); var fieldMap2 = cachedField.NodeAndDef; var fragmentNames2 = cachedField.Names; // Do not compare a fragment's fieldMap to itself. if (fieldMap == fieldMap2) { return; } // (D) First collect any conflicts between the provided collection of fields // and the collection of fields represented by the given fragment. CollectConflictsBetween( context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fieldMap2); // (E) Then collect any conflicts between the provided collection of fields // and any fragment names found in the given fragment. for (var i = 0; i < fragmentNames2.Count; i++) { CollectConflictsBetweenFieldsAndFragment( context, conflicts, cachedFieldsAndFragmentNames, comparedFragments, comparedFragmentPairs, areMutuallyExclusive, fieldMap, fragmentNames2[i]); } }
private List <Conflict> FindConflictsBetweenSubSelectionSets( ValidationContext context, Dictionary <SelectionSet, CachedField> cachedFieldsAndFragmentNames, PairSet comparedFragmentPairs, bool areMutuallyExclusive, IGraphType parentType1, SelectionSet selectionSet1, IGraphType parentType2, SelectionSet selectionSet2) { var conflicts = new List <Conflict>(); var cachedField1 = GetFieldsAndFragmentNames( context, cachedFieldsAndFragmentNames, parentType1, selectionSet1); var fieldMap1 = cachedField1.NodeAndDef; var fragmentNames1 = cachedField1.Names; var cachedField2 = GetFieldsAndFragmentNames( context, cachedFieldsAndFragmentNames, parentType2, selectionSet2); var fieldMap2 = cachedField2.NodeAndDef; var fragmentNames2 = cachedField2.Names; // (H) First, collect all conflicts between these two collections of field. CollectConflictsBetween( context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fieldMap2); // (I) Then collect conflicts between the first collection of fields and // those referenced by each fragment name associated with the second. if (fragmentNames2.Count != 0) { var comparedFragments = new ObjMap <bool>(); for (var j = 0; j < fragmentNames2.Count; j++) { CollectConflictsBetweenFieldsAndFragment( context, conflicts, cachedFieldsAndFragmentNames, comparedFragments, comparedFragmentPairs, areMutuallyExclusive, fieldMap1, fragmentNames2[j]); } } // (I) Then collect conflicts between the second collection of fields and // those referenced by each fragment name associated with the first. if (fragmentNames1.Count != 0) { var comparedFragments = new ObjMap <bool>(); for (var i = 0; i < fragmentNames1.Count; i++) { CollectConflictsBetweenFieldsAndFragment( context, conflicts, cachedFieldsAndFragmentNames, comparedFragments, comparedFragmentPairs, areMutuallyExclusive, fieldMap2, fragmentNames1[i]); } } // (J) Also collect conflicts between any fragment names by the first and // fragment names by the second. This compares each item in the first set of // names to each item in the second set of names. for (var i = 0; i < fragmentNames1.Count; i++) { for (var j = 0; j < fragmentNames2.Count; j++) { CollectConflictsBetweenFragments( context, conflicts, cachedFieldsAndFragmentNames, comparedFragmentPairs, areMutuallyExclusive, fragmentNames1[i], fragmentNames2[j]); } } return(conflicts); }
/// <summary> /// Recursively casts light into cells. Operates on a single octant. /// </summary> /// <param name="bitMap">The cell grid definition.</param> /// <param name="gridPosn">The player's position within the grid.</param> /// <param name="viewRadius">The view radius; can be a fractional value.</param> /// <param name="startColumn">Current column; pass 1 as initial value.</param> /// <param name="leftViewSlope">Slope of the left (upper) view edge; pass 1.0 as /// the initial value.</param> /// <param name="rightViewSlope">Slope of the right (lower) view edge; pass 0.0 as /// the initial value.</param> /// <param name="txfrm">Coordinate multipliers for the octant transform.</param> /// /// Maximum recursion depth is (Ceiling(viewRadius)). private static void CastLight(ObjMap objMap, Vector2 gridPosn, float viewRadius, int startColumn, float leftViewSlope, float rightViewSlope, OctantTransform txfrm) { //Debug.Assert(leftViewSlope >= rightViewSlope); // Used for distance test. float viewRadiusSq = viewRadius * viewRadius; int viewCeiling = (int)Mathf.Ceil(viewRadius); // Set true if the previous cell we encountered was blocked. bool prevWasBlocked = false; // As an optimization, when scanning past a block we keep track of the // rightmost corner (bottom-right) of the last one seen. If the next cell // is empty, we can use this instead of having to compute the top-right corner // of the empty cell. float savedRightSlope = -1; int xDim = objMap.getObjMap().GetLength(0); int yDim = objMap.getObjMap().GetLength(1); // Outer loop: walk across each column, stopping when we reach the visibility limit. for (int currentCol = startColumn; currentCol <= viewCeiling; currentCol++) { int xc = currentCol; // Inner loop: walk down the current column. We start at the top, where X==Y. // // TODO: we waste time walking across the entire column when the view area // is narrow. Experiment with computing the possible range of cells from // the slopes, and iterate over that instead. for (int yc = currentCol; yc >= 0; yc--) { // Translate local coordinates to grid coordinates. For the various octants // we need to invert one or both values, or swap X for Y. int gridX = (int)gridPosn.x + xc * txfrm.xx + yc * txfrm.xy; int gridY = (int)gridPosn.y + xc * txfrm.yx + yc * txfrm.yy; // Range-check the values. This lets us avoid the slope division for blocks // that are outside the grid. // // Note that, while we will stop at a solid column of blocks, we do always // start at the top of the column, which may be outside the grid if we're (say) // checking the first octant while positioned at the north edge of the map. if (gridX < 0 || gridX >= xDim || gridY < 0 || gridY >= yDim) { continue; } // Compute slopes to corners of current block. We use the top-left and // bottom-right corners. If we were iterating through a quadrant, rather than // an octant, we'd need to flip the corners we used when we hit the midpoint. // // Note these values will be outside the view angles for the blocks at the // ends -- left value > 1, right value < 0. float leftBlockSlope = (yc + 0.5f) / (xc - 0.5f); float rightBlockSlope = (yc - 0.5f) / (xc + 0.5f); // Check to see if the block is outside our view area. Note that we allow // a "corner hit" to make the block visible. Changing the tests to >= / <= // will reduce the number of cells visible through a corner (from a 3-wide // swath to a single diagonal line), and affect how far you can see past a block // as you approach it. This is mostly a matter of personal preference. if (rightBlockSlope > leftViewSlope) { // Block is above the left edge of our view area; skip. continue; } else if (leftBlockSlope < rightViewSlope) { // Block is below the right edge of our view area; we're done. break; } // This cell is visible, given infinite vision range. If it's also within // our finite vision range, light it up. // // To avoid having a single lit cell poking out N/S/E/W, use a fractional // viewRadius, e.g. 8.5. // // TODO: we're testing the middle of the cell for visibility. If we tested // the bottom-left corner, we could say definitively that no part of the // cell is visible, and reduce the view area as if it were a wall. This // could reduce iteration at the corners. float distanceSquared = xc * xc + yc * yc; if (distanceSquared <= viewRadiusSq) { //grid.SetLight(gridX, gridY, distanceSquared); objMap.castLight(gridX, gridY); lightenedArea.Add(objMap.getObject(gridX, gridY)); } bool curBlocked = objMap.isBlocking(gridX, gridY); // grid.IsWall(gridX, gridY); if (prevWasBlocked) { if (curBlocked) { // Still traversing a column of walls. savedRightSlope = rightBlockSlope; } else { // Found the end of the column of walls. Set the left edge of our // view area to the right corner of the last wall we saw. prevWasBlocked = false; leftViewSlope = savedRightSlope; } } else { if (curBlocked) { // Found a wall. Split the view area, recursively pursuing the // part to the left. The leftmost corner of the wall we just found // becomes the right boundary of the view area. // // If this is the first block in the column, the slope of the top-left // corner will be greater than the initial view slope (1.0). Handle // that here. if (leftBlockSlope <= leftViewSlope) { CastLight(objMap, gridPosn, viewRadius, currentCol + 1, leftViewSlope, leftBlockSlope, txfrm); } // Once that's done, we keep searching to the right (down the column), // looking for another opening. prevWasBlocked = true; savedRightSlope = rightBlockSlope; } } } // Open areas are handled recursively, with the function continuing to search to // the right (down the column). If we reach the bottom of the column without // finding an open cell, then the area defined by our view area is completely // obstructed, and we can stop working. if (prevWasBlocked) { break; } } }
public override void OnLoad() { GameCore.TheGameCore.TheGameEventHandler += TheGameCore_TheGameEventHandler; // create our shader program program = new ShaderProgram(VertexShader, FragmentShader); // SetupCamera(); // Camera.SetDirection(new Vector3(0, 0, -1)); // set up the projection and view matrix program.Use(); projectionMatrix = Matrix4.CreatePerspectiveFieldOfView(TheRenderStatus.Fov, (float)TheRenderStatus.Width / TheRenderStatus.Height, TheRenderStatus.ZNear, TheRenderStatus.ZFar); program["projection_matrix"].SetValue(projectionMatrix); program["model_matrix"].SetValue(Matrix4.Identity); program["light_direction"].SetValue(theEnvironment.LightDirection); program["enable_lighting"].SetValue(theEnvironment.Lighting); program["ambient"].SetValue(theEnvironment.LightAmbient); materialPoint = TheResourceManager.GetPlainColor(program, "GamePlainRed", Color.Red); materialLineMarker = TheResourceManager.GetPlainColor(program, "GamePlainGreenYellow", Color.GreenYellow); objMeshs = new List <IObjGroup>(); ObjGroup tempObjMesh2 = ObjLoader.LoadObjFileToObjMesh(program, @"./Resources/Models/Turret1.obj"); tempObjMesh2.Location = new Vector3(10, 0, 10); tempObjMesh2.Scale = Vector3.UnitScale * 0.3f; objMeshs.Add(tempObjMesh2); ObjMaterial tempMaterial = TheResourceManager.GetPlainColor(program, "GamePlainGreen", Color.Green); tileTextures = RenderObjects.RenderObjects.CreateTileTextures(new Size(20, 20), program); ObjGroup tempObjGroup = new ObjGroup(program); ObjObject tempObj = new ObjObject(ObjectPrimitives.CreateCube(new Vector3(0, 0, 0), new Vector3(1, 1, 1), true)) { Material = tileTextures[Tile.TileIds.Grass].Material }; // ObjObject tempObj = CreateCube(program, new Vector3(1, 1, 1), new Vector3(0, 0, 0)); tempObjGroup.AddObject(tempObj); objMeshs.Add(tempObjGroup); tempObjGroup = new ObjGroup(program); // tempObj = new ObjObject(ObjectPrimitives.CreateCube(new Vector3(2, 0, 0), new Vector3(3, 1, 1), true)) tempObj = new ObjObject(ObjectPrimitives.CreateCube(new Vector3(0, 0, 0), new Vector3(1, 1, 1), true)) { Material = tileTextures[Tile.TileIds.Road].Material }; tempObjGroup.AddObject(tempObj); tempObjGroup.Location = new Vector3(1, 0, 5); tempObjGroup.Orientation = Quaternion.FromAngleAxis((float)(Math.PI * 0.25), Vector3.Up); objMeshs.Add(tempObjGroup); tempObjGroup = new ObjGroup(program); tempObj = new ObjObject(ObjectPrimitives.CreateSquareWithNormalsYorZ(new Vector3(5, 1, 1), new Vector3(4, 0, 1), true)) { Material = tempMaterial }; tempObjGroup.AddObject(tempObj); tempObj = new ObjObject(ObjectPrimitives.CreateSquareWithNormalsYorZ(new Vector3(-1, 1, 1), new Vector3(-2, 0, 0), true)); tempObjGroup.AddObject(tempObj); objMeshs.Add(tempObjGroup); // tempObjGroup = new ObjGroup(program); // theTileObjects = GetTileObjects(); // tempObjGroup.AddObjects(theTileObjects); // objMeshs.Add(tempObjGroup); // objMeshs.AddRange(GetGameObjects()); thePaths = new ObjGroupPaths(program); objMeshs.Add(thePaths); Gl.UseProgram(0); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, 0); Gl.BindBuffer(BufferTarget.ArrayBuffer, 0); if (UseObjMap) { objTileMap = new ObjMap(TheGameStatus.TheMap, TheCamera); } }