private void GenerateTerrain() { if (densitySize.x > 0 && densitySize.y > 0 && densitySize.z > 0) { Stopwatch s = new Stopwatch(); s.Restart(); s.Start(); startPoint = new Vector3((int)startPoint.x, (int)startPoint.y, (int)startPoint.z); densitySize = new Vector3((int)densitySize.x, (int)densitySize.y, (int)densitySize.z); Vector4[] density = densityGenerator.GetDensity( densitySize, pointsSpace, startPoint, noiseScale, noiseWeight, octavesCount, amplitudeMultiplier, frequencyMultiplier, seed, sizeMultiplier); Vector4[,,] convertedDensity = ConvertArrayOfVector4To3DimensionalArray(density, densitySize * pointsSpace); DrawGizmosIfEnable(density); OctreeElement root = voxelsOctree.GetOctreeVoxel(convertedDensity); if (root != null) { marchingCubes.GenerateMesh(root, meshGameObject); } //marchingCubes.GenerateMesh(convertedDensity, meshGameObject); s.Stop(); //Debug.Log("ooo " + s.Elapsed.TotalMilliseconds); } }
private OctreeElement[] CreateVoxelsLeaf(Vector4[,,] density, Vector3 size, Vector3 currentPosition, Vector3 startPoint) { OctreeElement[] octreeElements = new OctreeElement[8]; int elements = 0; for (int x = (int)currentPosition.x; x < (int)currentPosition.x + 2; x++) { for (int y = (int)currentPosition.y; y < (int)currentPosition.y + 2; y++) { for (int z = (int)currentPosition.z; z < (int)currentPosition.z + 2; z++) { if (x <= (int)size.x - 1 && y <= (int)size.y - 1 && z <= (int)size.z - 1) { Voxel voxel = new Voxel((x, x + 1), (y, y + 1), (z, z + 1), new Vector2(x / bigSize.x, z / bigSize.z)); (float[,,] densityForVoxel, bool edge) = GetDensityForVoxel(density, new Vector3(x, y, z), startPoint); voxel.SetDensity(densityForVoxel); octreeElements[elements] = voxel; if (edge) { voxel.Edge = true; } } else { octreeElements[elements] = null; } elements++; } } } return(octreeElements); }
// Use this for initialization void Start() { boxCollider = GetComponent <BoxCollider>(); root = new OctreeElement(null, boxCollider.bounds, 0); toBeSplit.Enqueue(root); cellCount++; float doubleMinCellSize = minCellSize * 2f; while (toBeSplit.Count > 0) { var elem = toBeSplit.Dequeue(); elem.Empty = !Physics.CheckBox(elem.Bounds.center, elem.Bounds.extents, Quaternion.identity, mask, QueryTriggerInteraction.Ignore); if (elem.Bounds.size.magnitude > doubleMinCellSize && !elem.Empty) { elem.Split(); foreach (var child in elem.Children) { toBeSplit.Enqueue(child); cellCount++; } } } CalculateNeighborsRecursive(root); }
private OctreeElement GetNeighborRec(OctreeElement startNode, OctreeElement.Dir dir) { OctreeElement parent = startNode.Parent; if (parent == null) { return(null); } //find local neighbor int localIndex = Array.IndexOf(parent.Children, startNode); StorePositionAtDepth(parent.Depth, localIndex); int localNeighborIndex = OctreeElement.localNeighborIndex[localIndex][(int)dir]; if (localNeighborIndex >= 0) { return(parent.Children[localNeighborIndex]); } OctreeElement topmostNeighbor = GetNeighborRec(parent, dir); //this means the edge of the octree volume so we return null if (topmostNeighbor == null) { return(null); } //find the lowest mirrored child of the parent neighbor OctreeElement lowerMostReflectedChild = GetLowestChild(topmostNeighbor, dir, getNeighborStartingDepth); return(lowerMostReflectedChild); }
public OctreeElement(OctreeElement parent, Bounds bounds, int depth) { Parent = parent; Bounds = bounds; // TODO Raytrace down to find surface below, there may be a building or tree or similar here. approxBoundsHeight = Bounds.center.y + Terrain.activeTerrain.SampleHeight(Bounds.center); Depth = depth; }
public void Remove(T key) { OctreeElement element = elementByKey[key]; elementByKey.Remove(key); RemoveInternal(element, 0, IntVector3.zero, root); }
public void Split() { Children = new OctreeElement[splitDirs.Length]; for (int i = 0; i < Children.Length; i++) { Children[i] = new OctreeElement(this, new Bounds(Bounds.center + Vector3.Scale(splitDirs[i], Bounds.extents / 2f), Bounds.extents), Depth + 1); } }
public void Add(T key, Vector3 position) { OctreeElement element = new OctreeElement(); elementByKey.Add(key, element); AddInternal(position, 0, IntVector3.zero, root, element); }
private OctreeElement GetLowestChild(OctreeElement start, OctreeElement.Dir dir, int maxDepth) { if (start.Children != null && start.Depth < maxDepth) { OctreeElement.Pos reflectedPos = OctreeElement.ReflectedPos[(int)dir][neighborPathPositions[start.Depth]]; return(GetLowestChild(start.Children[(int)reflectedPos], dir, maxDepth)); } return(start); }
private void GetNeighbors(OctreeElement startNode, OctreeElement.Dir dir, ICollection <OctreeElement> neighbors) { getNeighborStartingDepth = startNode.Depth; var topmostNeighbor = GetNeighborRec(startNode, dir); if (topmostNeighbor != null) { GetAllChildrentInDir(topmostNeighbor, dir, neighbors); } }
public void addEntity(Entity e, Vector3 pos) { OctreeElement <Entity> el = new OctreeElement <Entity>(); el.myObject = e; el.mySize = 2; //need to figure out the best way to get this info, default of 2 is fine for now convertPosition(ref el, pos); theOctree.insert(el); theOctreeEntityMap.Add(e.id, el); myReverseOctreeEntityMap.Add(el, e.id); }
public void Update(T key, Vector3 newPosition) { OctreeElement element = elementByKey[key]; element.position = newPosition; if (WithinBox(newPosition, GetMin(element.level, element.coords), GetMax(element.level, element.coords))) { return; } RemoveInternal(element, 0, IntVector3.zero, root); AddInternal(newPosition, 0, IntVector3.zero, root, element); }
private void MoveToChild(OctreeElement element, int childIndex) { if (children[childIndex] == null) { children[childIndex] = new OctreeNode(); } element.level += 1; element.coords = element.coords * 2 + ChildIndexToCoords(childIndex); children[childIndex].Put(element); children[childIndex].TotalElementCount++; }
/// <summary> /// Get the smallest known node that encompasses the position. /// </summary> /// <param name="position">The position that must be containers</param> /// <returns>The smallest node containing the position or null if the octree does not contain the position.</returns> internal OctreeElement GetNode(Vector3 position) { OctreeElement node = GetNode(root, position); #if UNITY_EDITOR if (node == null) { Debug.LogError("Requested a node containing a position " + position + " which is not within the Octree. This should not happen. First check that the position is within the Octree using Contains(position)"); } #endif return(node); }
public Entity nearestNeighbor(Entity e) { OctreeElement <Entity> el; if (theOctreeEntityMap.TryGetValue(e.id, out el)) { OctreeElement <Entity> nel = theOctree.nearestNeighbor(el); if (nel != null) { return(nel.myObject); } } return(null); }
private void GetAllChildrentInDir(OctreeElement start, OctreeElement.Dir dir, ICollection <OctreeElement> elements) { if (start.Children != null) { var oppositeDir = (int)OctreeElement.OppositeDirs[(int)dir]; for (int i = 0; i < OctreeElement.PosInDir[oppositeDir].Length; i++) { GetAllChildrentInDir(start.Children[(int)OctreeElement.PosInDir[oppositeDir][i]], dir, elements); } } else { elements.Add(start); } }
public OctreeElement GetOctreeVoxel(Vector4[,,] density) { if (density.GetLength(0) > 1 && density.GetLength(1) > 1 && density.GetLength(2) > 1) { int treeSize = GetTreeSize(density.GetLength(0) - 1, density.GetLength(1) - 1, density.GetLength(2) - 1); // Debug.Log("treeSize: " + treeSize); List <OctreeElement> branchesWithVoxels = InitVoxels(density); float xDifferent = density[1, 0, 0].x - density[0, 0, 0].x; float yDifferent = density[0, 1, 0].y - density[0, 0, 0].y; float zDifferent = density[0, 0, 1].z - density[0, 0, 0].z; Vector3 size = new Vector3(density.GetLength(0), density.GetLength(1), density.GetLength(2)); Vector3 startPoint = new Vector3(density[0, 0, 0].x, density[0, 0, 0].y, density[0, 0, 0].z); List <OctreeElement> branchesChildren = branchesWithVoxels; List <OctreeElement> biggerBranches = new List <OctreeElement>(); while (branchesChildren.Count > 1) { FillNextLevelOfTree(branchesChildren, biggerBranches, xDifferent, yDifferent, zDifferent, size, startPoint); xDifferent *= 2; yDifferent *= 2; zDifferent *= 2; branchesChildren = biggerBranches; biggerBranches = new List <OctreeElement>(); } root = branchesChildren[0]; SetVoxelsType(root); SetVoxelsType(root); SetVoxelsType(root); SetVoxelsType(root); SetVoxelsType(root); SetVoxelsType(root); SetVoxelsType(root); return(root); } return(null); }
public void GenerateMesh(OctreeElement root, GameObject terrain) { meshVertices = new List <Vector3>(); uv = new List <Vector2>(); if (VertexesCaseProvider.ReadVerticesIndexesFromFile()) { List <OctreeElement> octreeBranches = root.NextElements.ToList(); while (octreeBranches.Count != 0) { int count = octreeBranches.Count; for (int i = count - 1; i >= 0; i--) { if (octreeBranches[i] != null) { OctreeElement[] nextElements = octreeBranches[i].NextElements; if (nextElements == null) { Voxel voxel = octreeBranches[i] as Voxel; if (voxel.Drawable) { foreach (var vertices in voxel.Vertices) { meshVertices.AddRange(vertices); uv.AddRange(voxel.GetUVPositionForVoxel()); } } } else { octreeBranches.AddRange(nextElements); } } octreeBranches.RemoveAt(i); } } } GenerateMesh(terrain); }
private void CalculateNeighborsRecursive(OctreeElement element) { if (element.Children == null) { element.Neigbors = new OctreeElement[6][]; for (int i = 0; i < 6; i++) { List <OctreeElement> neighbors = new List <OctreeElement>(); GetNeighbors(element, (OctreeElement.Dir)i, neighbors); element.Neigbors[i] = neighbors.ToArray(); } } else { for (int i = 0; i < element.Children.Length; i++) { CalculateNeighborsRecursive(element.Children[i]); } } }
/// <summary> /// Get the smallest known node that encompasses the position. /// If the supplied parent node has children and it encompasses the position /// work through the children until the one that contains the position is found. /// This is repeated recursively to return the smallest node possible. /// </summary> /// <param name="parent">The node to start the search within.</param> /// <param name="position">The position that must be containers</param> /// <returns>The smallest child node containing the position or null if the parent does not contain the position.</returns> private OctreeElement GetNode(OctreeElement parent, Vector3 position) { if (parent.Bounds.Contains(position)) { if (parent.Children != null) { for (int i = 0; i < parent.Children.Length; i++) { OctreeElement child = GetNode(parent.Children[i], position); if (child != null) { return(child); } } } else { return(parent); } } return(null); }
private OctreeElement GetNode(OctreeElement parent) { if (parent.Bounds.Contains(tmpGetNodePos)) { if (parent.Children != null) { for (int i = 0; i < parent.Children.Length; i++) { OctreeElement child = GetNode(parent.Children[i]); if (child != null) { return(child); } } } else { return(parent); } } return(null); }
//returns whether or not the value changed public bool convertPosition(ref OctreeElement <Entity> element, Vector3 pos) { uint X, Y, Z; X = (uint)pos.X; Y = (uint)pos.Y; Z = (uint)pos.Z; bool needsUpdate = false; if (X != element.myX || Y != element.myY || Z != element.myZ) { needsUpdate = true; } //for the moment, just a straight passthrough element.myX = X; element.myY = Y; element.myZ = Z; return(needsUpdate); }
private void RemoveInternal(OctreeElement element, int level, IntVector3 coords, OctreeNode node) { node.TotalElementCount--; if (element.level == level) { node.Remove(element.index); return; } IntVector3 coordsInChildLevel = element.coords / (1 << (element.level - level - 1)); IntVector3 childCoords = coordsInChildLevel - coords * 2; int childIndex = ChildCoordsToIndex(childCoords); OctreeNode child = node.children[childIndex]; RemoveInternal(element, level + 1, coordsInChildLevel, child); if (child.TotalElementCount == 0) { node.children[childIndex] = null; } if (node.TotalElementCount <= mergeThreshold) { node.Merge(); } }
public void SetVoxelsType(OctreeElement root) { Stopwatch d = new Stopwatch(); d.Restart(); List <OctreeElement> octreeBranches = root.NextElements.ToList(); while (octreeBranches.Count != 0) { int count = octreeBranches.Count; for (int i = count - 1; i >= 0; i--) { if (octreeBranches[i] != null) { OctreeElement[] nextElements = octreeBranches[i].NextElements; if (nextElements == null) { Voxel voxel = octreeBranches[i] as Voxel; voxel.SetType(); } else { octreeBranches.AddRange(nextElements); } } octreeBranches.RemoveAt(i); } } d.Stop(); //Debug.Log("d: " + d.Elapsed.TotalMilliseconds); }
public OctreeBranch(OctreeElement previousElement) : base(previousElement, false) { }
private void MoveFromChild(OctreeElement element) { element.level -= 1; element.coords = element.coords / 2; Put(element); }
public void GetPathAstar(object context) { PathRequest request = (PathRequest)context; try { FastPriorityQueue <OctreeElementQueueElemenet> fronteer = new FastPriorityQueue <OctreeElementQueueElemenet>(16); Dictionary <OctreeElement, OctreeElement> cameFrom = new Dictionary <OctreeElement, OctreeElement>(); Dictionary <OctreeElement, float> weights = new Dictionary <OctreeElement, float>(); OctreeElement startNode = GetNode(request.from); OctreeElement endNode = GetNode(request.to); if (startNode == null || endNode == null) { return; } weights.Add(startNode, startNode.BaseCost); fronteer.Enqueue(new OctreeElementQueueElemenet(startNode), startNode.WeightedCost(request.controller.preferredFlightHeight, request.controller.minFlightHeight, request.controller.maxFlightHeight)); OctreeElement current; OctreeElement closest = startNode; float closestDistance = Vector3.SqrMagnitude(startNode.Bounds.center - request.to); long lastMiliseconds = 0; Stopwatch stopwatch = Stopwatch.StartNew(); while (fronteer.Count > 0) { current = fronteer.Dequeue().Element; if (current == endNode) { break; } //still building path if (current.Neigbors != null) { for (int i = 0; i < 6; i++) { for (int n = 0; n < current.Neigbors[i].Length; n++) { var next = current.Neigbors[i][n]; if (!next.Empty && next != endNode) { continue; } float sqrDistance = Vector3.SqrMagnitude(next.Bounds.center - request.to); if (sqrDistance < closestDistance) { closestDistance = sqrDistance; closest = next; } float distance = (next.Bounds.center - request.to).sqrMagnitude; float newWeight = weights[current] + next.WeightedCost(request.controller.preferredFlightHeight, request.controller.minFlightHeight, request.controller.maxFlightHeight) + distance; if (!weights.ContainsKey(next) || newWeight < weights[next]) { weights[next] = newWeight; cameFrom[next] = current; if (fronteer.MaxSize <= fronteer.Count) { fronteer.Resize(fronteer.MaxSize * 2); } fronteer.Enqueue(new OctreeElementQueueElemenet(next), newWeight + distance); } } } } if (maxMilisecondsPerFrame > 0 && stopwatch.ElapsedMilliseconds - lastMiliseconds > maxMilisecondsPerFrame) { lastMiliseconds = stopwatch.ElapsedMilliseconds; Thread.Sleep(1); } } current = endNode; bool particalPath = false; while (current != startNode) { if (!cameFrom.TryGetValue(current, out current)) { particalPath = true; current = closest; } request.path.Insert(0, current.Bounds.center); } if (!particalPath) { request.path.Add(request.to); } request.isCalulated = true; } catch (Exception e) { throw e; } finally { request.isCalculating = false; } }
private void AddInternal(Vector3 position, int level, IntVector3 coords, OctreeNode node, OctreeElement element) { if (node.NodeElementCount >= splitThreshold && level < maxLevel) { Vector3 center = GetCenter(level, coords); node.Split(center); } node.TotalElementCount++; if (!node.IsLeaf) { Vector3 center = GetCenter(level, coords); int childIndex = PositionToChildIndex(position, center); OctreeNode child = node.GetOrCreateChild(childIndex); AddInternal(position, level + 1, coords * 2 + ChildIndexToCoords(childIndex), child, element); return; } element.position = position; element.level = level; element.coords = coords; node.Put(element); //Debug.Log(element.ToString() + " is added at " + Time.time); }
public OctreeElementQueueElemenet(OctreeElement element) { Element = element; }
public OctreeElement(OctreeElement parent, Bounds bounds, int depth) { Parent = parent; Bounds = bounds; Depth = depth; }