/// Constructs a Region from corners specified as Vector3i parameters. public Region(Vector3i lowerCorner, Vector3i upperCorner) { this.lowerCorner = lowerCorner; this.upperCorner = upperCorner; }
/// Constructs a vector by copying the supplied vector. public Vector3i(Vector3i a) { this.x = a.x; this.y = a.y; this.z = a.z; }
/// Constructs a Region from corners specified as seperate integer parameters. public Region(int lowerX, int lowerY, int lowerZ, int upperX, int upperY, int upperZ) { lowerCorner = new Vector3i(lowerX, lowerY, lowerZ); upperCorner = new Vector3i(upperX, upperY, upperZ); }
/// Component-wise minimum of one vector and another, returning a new vector as the result. public static Vector3i Min(Vector3i lhs, Vector3i rhs) { return new Vector3i(Mathf.Min(lhs.x, rhs.x), Mathf.Min(lhs.y, rhs.y), Mathf.Min(lhs.z, rhs.z)); }
/// Scales 'a' by 'b' and returns the result. public static Vector3i Scale(Vector3i a, Vector3i b) { return new Vector3i(a.x * b.x, a.y * b.y, a.z * b.z); }
/// Computes the distance between two positions. public static float Distance(Vector3i a, Vector3i b) { return Mathf.Sqrt(DistanceSquared(a, b)); }
/// Computes the squared distance between two positions. public static int DistanceSquared(Vector3i a, Vector3i b) { int dx = b.x - a.x; int dy = b.y - a.y; int dz = b.z - a.z; return dx * dx + dy * dy + dz * dz; }
private void Update() { if (flushRequested) { FlushInternalData(); flushRequested = false; // It seems prudent to return at this point, and leave the actual updating to the next call of this function. // This is because we've just destroyed a bunch of stuff by flushing and Unity actually defers Destroy() until // later in the frame. It actually seems t work ok without the return, but it makes me feel a little safer. return; } // Check whether the gameObject has been moved to a new layer. if (gameObject.layer != previousLayer) { // If so we update the children to match and then clear the flag. gameObject.SetLayerRecursively(gameObject.layer); previousLayer = gameObject.layer; } // Set shader parameters. VolumeRenderer volumeRenderer = gameObject.GetComponent <VolumeRenderer>(); if (volumeRenderer != null) { if (volumeRenderer.material != null) { Vector3i volumeSize = (data.enclosingRegion.upperCorner - data.enclosingRegion.lowerCorner); volumeSize.x++; volumeSize.y++; volumeSize.z++; volumeRenderer.material.SetVector("_VolumeSize", (Vector3)volumeSize); // NOTE - The following line passes transform.worldToLocalMatrix as a shader parameter. This is explicitly // forbidden by the Unity docs which say: // // IMPORTANT: If you're setting shader parameters you MUST use Renderer.worldToLocalMatrix instead. // // However, we don't have a renderer on this game object as the rendering is handled by the child OctreeNodes. // The Unity doc's do not say why this is the case, but my best guess is that it is related to secret scaling // which Unity may perform before sending data to the GPU (probably to avoid precision problems). See here: // // http://forum.unity3d.com/threads/153328-How-to-reproduce-_Object2World // // It seems to work in our case, even with non-uniform scaling applied to the volume. Perhaps we are just geting // lucky, pehaps it just works on our platform, or perhaps it is actually valid for some other reason. Just be aware. volumeRenderer.material.SetMatrix("_World2Volume", transform.worldToLocalMatrix); } } if (data != null && data.volumeHandle.HasValue) { // When we are in game mode we limit the number of nodes which we update per frame, to maintain a nice. // framerate The Update() method is called repeatedly and so over time the whole mesh gets syncronized. if (Application.isPlaying) { isMeshSyncronized = SynchronizeOctree(maxSyncOperationsInPlayMode); } else { isMeshSyncronized = SynchronizeOctree(maxSyncOperationsInEditMode); } } }
/// Component-wise clamping of one vector and another, returning a new vector as the result. public static Vector3i Clamp(Vector3i value, Vector3i min, Vector3i max) { return new Vector3i(Mathf.Clamp(value.x, min.x, max.x), Mathf.Clamp(value.y, min.y, max.y), Mathf.Clamp(value.z, min.z, max.z)); }
/// Component-wise clamping of one vector and another, returning a new vector as the result. public static Vector3i Clamp(Vector3i value, Vector3i min, Vector3i max) { return(new Vector3i(Mathf.Clamp(value.x, min.x, max.x), Mathf.Clamp(value.y, min.y, max.y), Mathf.Clamp(value.z, min.z, max.z))); }
/// Component-wise maximum of one vector and another, returning a new vector as the result. public static Vector3i Max(Vector3i lhs, Vector3i rhs) { return(new Vector3i(Mathf.Max(lhs.x, rhs.x), Mathf.Max(lhs.y, rhs.y), Mathf.Max(lhs.z, rhs.z))); }
/// Computes the distance between two positions. public static float Distance(Vector3i a, Vector3i b) { return(Mathf.Sqrt(DistanceSquared(a, b))); }
/// Scales 'a' by 'b' and returns the result. public static Vector3i Scale(Vector3i a, Vector3i b) { return(new Vector3i(a.x * b.x, a.y * b.y, a.z * b.z)); }