Example #1
0
 public UpdateCheckJob(VoxelBlock block, VoxelTree control, byte detailLevel)
 {
     this.block       = block;
     this.control     = control;
     this.detailLevel = detailLevel;
     control.addUpdateCheckJob();
 }
        protected void apply(Application app, VoxelBlock block, Index pos)
        {
            Index cornerChild = pos.getChild();
            for(byte c = 0; c<VoxelBlock.CHILD_COUNT; ++c) {
                // TODO: use min and max to reduce number of values considered
                Index childPos = cornerChild.getNeighbor(c);
                Action action = checkMutation(app, childPos);

                // check if voxel is outside of modifier area
                if (!action.modify)
                    continue;

                // check if voxel is inside of masked area
                Action maskAction = checkMasks(app.tree, childPos);
                if (!maskAction.modify)
                    continue;

                // recurse or set full voxel
                if (childPos.depth < app.tree.maximumDetail && (maskAction.doTraverse || action.doTraverse))
                    apply(app, block.expand(childPos.xLocal, childPos.yLocal, childPos.zLocal), childPos);
                else
                    block.children[childPos.xLocal, childPos.yLocal, childPos.zLocal] =
                        mutate(app, childPos, action, block.children[childPos.xLocal, childPos.yLocal, childPos.zLocal].toVoxel());

                // update meshes if appropriate
                if (childPos.depth == app.tree.maximumDetail - VoxelRenderer.VOXEL_COUNT_POWER) {
                    UpdateCheckJob job = new UpdateCheckJob(block, app.tree, childPos.depth);
                    job.setOffset((byte)childPos.x, (byte)childPos.y, (byte)childPos.z);
                    job.setForce(true);
                    app.jobs.Add(job);
                }
            }
        }
Example #3
0
        public virtual void initialize()
        {
//			float startTime = Time.realtimeSinceStartup;

            // setup lookup tables, etc.
            sizes = new float[maxDetail + 1];
            float s = baseSize;

            for (int i = 0; i <= maxDetail; ++i)
            {
                sizes[i] = s;
                s       /= 2;
            }
            updateCheckJobs = 0;

            // initialize voxels
            head = new VoxelBlock();
//			genData(0);

//			float endTime = Time.realtimeSinceStartup;


//			print("Voxel Gen time:                   " + (endTime - startTime));
//			print("Average Voxel Opacity:            " + head.averageOpacity());
//			print("Total Voxel Blocks:               " + VoxelHolder.blockCount);
//			print("Total Tree Count:                 " + treeCount);
//			print("Renderer Count:                   " + VoxelRenderer.rendCount);
//			print("Duplicate Triangle Count:         " + VoxelRenderer.duplicateTriangleCount);
        }
Example #4
0
 public void set(byte detailLevel, int x, int y, int z, Voxel value, Tree control)
 {
     if (detailLevel > 0)
     {
         short factor = (short)(1 << (detailLevel - CHILD_COUNT_POWER));
         byte  xi     = (byte)(x / factor);
         byte  yi     = (byte)(y / factor);
         byte  zi     = (byte)(z / factor);
         if (detailLevel == CHILD_COUNT_POWER)
         {
             children[xi, yi, zi] = value;
         }
         else
         {
             if (children[xi, yi, zi].GetType() == typeof(Voxel))
             {
                 if (children[xi, yi, zi].Equals(value))
                 {
                     ++skippedSubdivisions; return;
                 }
                 children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
             }
             ((VoxelBlock)children[xi, yi, zi]).set((byte)(detailLevel - CHILD_COUNT_POWER), x - xi * factor, y - yi * factor, z - zi * factor, value, control);
         }
     }
     else
     {
         set(value);
     }
 }
Example #5
0
        public void updateAll(int x, int y, int z, byte detailLevel, VoxelTree control, bool force = false)
        {
            // check if this is a high enough detail level.  If not, call the childrens' update methods
            if (!isRenderSize(control.sizes[detailLevel], control) && (!isRenderLod(x, y, z, control.sizes[detailLevel], control)))
            {
                for (byte xi = 0; xi < CHILD_DIMENSION; ++xi)
                {
                    for (byte yi = 0; yi < CHILD_DIMENSION; ++yi)
                    {
                        for (byte zi = 0; zi < CHILD_DIMENSION; ++zi)
                        {
                            //VoxelUpdateInfo childInfo = new VoxelUpdateInfo(info, xi, yi, zi);
                            if (children[xi, yi, zi].GetType() == typeof(Voxel))
                            {
                                //if (!childInfo.isSolid())
                                children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
                                //else
                                //continue;
                            }
                            UpdateCheckJob job = new UpdateCheckJob((VoxelBlock)children[xi, yi, zi], control, (byte)(detailLevel + 1));
                            job.setOffset((byte)(x * CHILD_DIMENSION + xi), (byte)(y * CHILD_DIMENSION + yi), (byte)(z * CHILD_DIMENSION + zi));
                            control.enqueueCheck(job);
                        }
                    }
                }
                if (renderer != null)
                {
                    //GameObject.Destroy(renderer.ob);
                    //lock (myControl) {
                    //	myControl.enqueueJob(new DropRendererJob(renderer));
                    //	renderer = null;
                    //}
                    renderer.old = true;
                }
                return;
            }

            // check if we already have a mesh
            if (renderer == null)
            {
                //clearSubRenderers();
                renderer = new VoxelRenderer(new VoxelIndex(x, y, z, detailLevel), control);
                //info.renderers[1, 1, 1] = renderer;
            }
            else
            {
                renderer.old = false;
                if (!force)
                {
                    return;
                }
            }

            // We should generate a mesh
            GenMeshJob updateJob = new GenMeshJob(this, control, detailLevel);

            updateJob.setOffset(x, y, z);
            control.enqueueUpdate(updateJob);
        }
Example #6
0
 public VoxelBlock expand(uint x, uint y, uint z)
 {
     if (children[x, y, z].GetType() == typeof(Voxel))
     {
         children[x, y, z] = new VoxelBlock((Voxel)children[x, y, z]);
     }
     return((VoxelBlock)children[x, y, z]);
 }
Example #7
0
 public void wipe()
 {
     clearRenderers();
     if (head != null)
     {
         head = null;
     }
     dirty = true;
 }
Example #8
0
        public override void execute()
        {
            //MonoBehaviour.print("APPLYING!");
            Vector3 pos = rend.position / rend.size;

            if (VoxelBlock.isRenderLod(pos.x, pos.y, pos.z, rend.size, rend.control) || VoxelBlock.isRenderSize(rend.size, rend.control))
            {
                rend.applyMesh(detailLevel, x, y, z);
            }
        }
Example #9
0
        protected void traverse(VoxelUpdateInfo info, byte detailLevel)
        {
            int  factor = 1 << (detailLevel - VoxelBlock.CHILD_COUNT_POWER);
            byte xiMin  = (byte)Mathf.Max(minX / factor - info.x * VoxelBlock.CHILD_DIMENSION, 0f);
            byte xiMax  = (byte)Mathf.Min((maxX + 1) / factor - info.x * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f);
            byte yiMin  = (byte)Mathf.Max(minY / factor - info.y * VoxelBlock.CHILD_DIMENSION, 0f);
            byte yiMax  = (byte)Mathf.Min((maxY + 1) / factor - info.y * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f);
            byte ziMin  = (byte)Mathf.Max(minZ / factor - info.z * VoxelBlock.CHILD_DIMENSION, 0f);
            byte ziMax  = (byte)Mathf.Min((maxZ + 1) / factor - info.z * VoxelBlock.CHILD_DIMENSION, VoxelBlock.CHILD_DIMENSION - 1f);

            VoxelBlock block = (VoxelBlock)info.blocks[1, 1, 1];

            uint scale = (uint)(1 << (VoxelBlock.CHILD_COUNT_POWER * (detailLevel - 1)));

            for (byte yi = yiMin; yi <= yiMax; ++yi)
            {
                if ((info.y * VoxelBlock.CHILD_DIMENSION + yi) < maskMinY / scale ||
                    (info.y * VoxelBlock.CHILD_DIMENSION + yi) > maskMaxY / scale + 1)
                {
                    continue;
                }

                for (byte xi = xiMin; xi <= xiMax; ++xi)
                {
                    for (byte zi = ziMin; zi <= ziMax; ++zi)
                    {
                        if (detailLevel <= VoxelBlock.CHILD_COUNT_POWER)
                        {
                            block.children[xi, yi, zi] = modifyVoxel(block.children[xi, yi, zi], info.x * VoxelBlock.CHILD_DIMENSION + xi, info.y * VoxelBlock.CHILD_DIMENSION + yi, info.z * VoxelBlock.CHILD_DIMENSION + zi);
                        }
                        else
                        {
                            if (block.children[xi, yi, zi].GetType() == typeof(Voxel))
                            {
                                block.children[xi, yi, zi] = new VoxelBlock((Voxel)block.children[xi, yi, zi]);
                            }
                            traverse(new VoxelUpdateInfo(info, xi, yi, zi), (byte)(detailLevel - VoxelBlock.CHILD_COUNT_POWER));
                        }
                    }
                }
            }

            if (updateMesh && info != null && (VoxelBlock.isRenderSize(info.size, control) || VoxelBlock.isRenderLod(info.x, info.y, info.z, info.size, control)))
            {
                //block.clearSubRenderers(control);
                block.updateAll(info.x, info.y, info.z, info.detailLevel, control, true);
            }
        }
Example #10
0
		public void set(byte detailLevel, int x, int y, int z, Voxel value, Tree control) {
			if (detailLevel > 0) {
				short factor = (short)(1 << (detailLevel - CHILD_COUNT_POWER));
				byte xi = (byte)(x / factor);
				byte yi = (byte)(y / factor);
				byte zi = (byte)(z / factor);
				if (detailLevel == CHILD_COUNT_POWER) {
					children[xi, yi, zi] = value;
				} else {
					if (children[xi, yi, zi].GetType() == typeof(Voxel)) {
						if (children[xi, yi, zi].Equals(value)) { ++skippedSubdivisions; return; }
						children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
					}
					((VoxelBlock)children[xi, yi, zi]).set((byte)(detailLevel - CHILD_COUNT_POWER), x - xi * factor, y - yi * factor, z - zi * factor, value, control);
				}
			} else
				set(value);
		}
Example #11
0
        public void OnAfterDeserialize()
        {
            //			clearRenderers();
            //print("Deserializing");
            lock (this) {
                if (voxelData.Length > 0)
                {
                    MemoryStream stream = new MemoryStream(voxelData);
                    BinaryReader reader = new BinaryReader(stream);
                    head = (VoxelBlock)VoxelHolder.deserialize(reader);
                    stream.Close();
                }

                // relink renderers
                //relinkRenderers();
                enqueueJob(new LinkRenderersJob(this));
            }
        }
Example #12
0
        public bool import(string fileName)
        {
            clearRenderers();
            Stream       stream            = File.OpenRead(fileName);
            BinaryReader reader            = new BinaryReader(stream);
            ulong        fileFormatVersion = reader.ReadUInt64();

            if (fileFormatVersion != FILE_FORMAT_VERSION)
            {
                stream.Close();
                print("Wrong voxel file format version: " + fileFormatVersion + ", should be " + FILE_FORMAT_VERSION);
                return(false);
            }
            else
            {
                head  = (VoxelBlock)VoxelHolder.deserialize(reader);
                dirty = true;
                stream.Close();
                return(true);
            }
        }
Example #13
0
 public GenMeshJob(VoxelBlock block, VoxelTree control, byte detailLevel)
 {
     this.block = block;
     this.control = control;
     this.detailLevel = detailLevel;
 }
Example #14
0
 public UpdateCheckJob(VoxelBlock block, VoxelTree control, byte detailLevel)
 {
     this.block = block;
     this.control = control;
     this.detailLevel = detailLevel;
     control.addUpdateCheckJob();
 }
Example #15
0
		public void updateAll(uint x, uint y, uint z, byte detailLevel, Tree control, bool force = false) {
			// check if this is a high enough detail level.  If not, call the childrens' update methods
			VoxelRenderer renderer = control.getRenderer(new Index(detailLevel, x, y, z));
			if (!isRenderSize(control.sizes[detailLevel], control) && (!isRenderLod(x, y, z, control.sizes[detailLevel], control))) {
				for (byte xi = 0; xi < CHILD_DIMENSION; ++xi) {
					for (byte yi = 0; yi < CHILD_DIMENSION; ++yi) {
						for (byte zi = 0; zi < CHILD_DIMENSION; ++zi) {
							//VoxelUpdateInfo childInfo = new VoxelUpdateInfo(info, xi, yi, zi);
							if (children[xi, yi, zi].GetType() == typeof(Voxel)) {
								//if (!childInfo.isSolid())
								children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
								//else
								//continue;
							}
							UpdateCheckJob job = new UpdateCheckJob((VoxelBlock)children[xi, yi, zi], control, (byte)(detailLevel + 1));
							job.setOffset((byte)(x * CHILD_DIMENSION + xi), (byte)(y * CHILD_DIMENSION + yi), (byte)(z * CHILD_DIMENSION + zi));
							control.enqueueCheck(job);
						}
					}
				}
				if (renderer != null) {
					//GameObject.Destroy(renderer.ob);
					//lock (myControl) {
					//	myControl.enqueueJob(new DropRendererJob(renderer));
					//	renderer = null;
					//}
					renderer.old = true;
				}
				return;
			}

			// check if we already have a mesh
			if (renderer == null) {
				//clearSubRenderers();
				renderer = new VoxelRenderer(new Index(detailLevel, x, y, z), control);
				//info.renderers[1, 1, 1] = renderer;
			} else {
				renderer.old = false;
				if (!force) return;
			}

			// We should generate a mesh
			GenMeshJob updateJob = new GenMeshJob(this, control, detailLevel);
			updateJob.setOffset(x, y, z);
			control.enqueueUpdate(updateJob);
		}
        public void setToHeightmap(byte detailLevel, int x, int y, int z, ref float[,] map, byte[,] mats, OcTree control)
        {
            if (detailLevel <= CHILD_COUNT_POWER) {
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi) {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi) {
                        for (int yi = 0; yi < CHILD_DIMENSION; ++yi) {
                            if (yi + y >= map[x + xi, z + zi])
                                break;
                            else if (yi + y >= map[x + xi, z + zi] - 1) {
                                if (mats[x + xi, z + zi] == byte.MaxValue)
                                    children[xi, yi, zi] = Voxel.empty;
                                else
                                    children[xi, yi, zi] = new Voxel(mats[x + xi, z + zi], (byte)((map[x + xi, z + zi] - yi - y) * byte.MaxValue));
                            } else {
                                if (mats[x + xi, z + zi] == byte.MaxValue)
                                    children[xi, yi, zi] = Voxel.empty;
                                else
                                    children[xi, yi, zi] = new Voxel(mats[x + xi, z + zi], byte.MaxValue);
                            }
                        }
                    }
                }
            } else {
                int multiplier = (1 << (detailLevel - CHILD_COUNT_POWER));
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi) {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi) {
                        int xMax = x + (xi + 1) * multiplier;
                        int zMax = z + (zi + 1) * multiplier;
                        float yMin = float.MaxValue;
                        float yMax = 0;
                        bool multipleMaterials = false;
                        byte material = mats[x, z];
                        for (int xPos = x + xi * multiplier; xPos < xMax; ++xPos) {
                            for (int zPos = z + zi * multiplier; zPos < zMax; ++zPos) {
                                if (map[xPos, zPos] < yMin) yMin = map[xPos, zPos];
                                if (map[xPos, zPos] > yMax) yMax = map[xPos, zPos];
                                if (mats[xPos, zPos] != material) multipleMaterials = true;
                            }
                        }

                        if (multipleMaterials) yMin = 0;
                        int firstUnsolidBlock = Mathf.Min(((int)(yMin - y)) / multiplier, CHILD_DIMENSION);
                        int lastUnsolidBlock = Mathf.Min(((int)(yMax - y)) / multiplier, CHILD_DIMENSION - 1);
                        int yi = 0;
                        for (; yi < firstUnsolidBlock; ++yi) {
                            if (mats[x + xi * multiplier, z + zi * multiplier] == byte.MaxValue)
                                children[xi, yi, zi] = Voxel.empty;
                            else
                                children[xi, yi, zi] = new Voxel(mats[x + xi * multiplier, z + zi * multiplier], byte.MaxValue);
                        }
                        if (lastUnsolidBlock < 0) continue;
                        for (; yi <= lastUnsolidBlock; ++yi) {
                            VoxelBlock newChild = new VoxelBlock();
                            newChild.setToHeightmap((byte)(detailLevel - CHILD_COUNT_POWER), x + xi * multiplier, y + yi * multiplier, z + zi * multiplier, ref map, mats, control);
                            children[xi, yi, zi] = newChild;
                        }
                    }
                }
            }
            control.dirty = true;
        }
        public void updateAll(uint x, uint y, uint z, byte detailLevel, OcTree control, bool force = false)
        {
            // check if this is a high enough detail level.  If not, call the childrens' update methods
            VoxelRenderer renderer = control.getRenderer(new Index(detailLevel, x, y, z));
            if (!isRenderSize(control.sizes[detailLevel], control) && (!isRenderLod(x, y, z, control.sizes[detailLevel], control))) {
                for (byte xi = 0; xi < CHILD_DIMENSION; ++xi) {
                    for (byte yi = 0; yi < CHILD_DIMENSION; ++yi) {
                        for (byte zi = 0; zi < CHILD_DIMENSION; ++zi) {
                            if (children[xi, yi, zi].GetType() == typeof(Voxel)) {
                                children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
                            }
                            UpdateCheckJob job = new UpdateCheckJob((VoxelBlock)children[xi, yi, zi], control, (byte)(detailLevel + 1));
                            job.setOffset((byte)(x * CHILD_DIMENSION + xi), (byte)(y * CHILD_DIMENSION + yi), (byte)(z * CHILD_DIMENSION + zi));
                            control.enqueueCheck(job);
                        }
                    }
                }
                return;
            }

            // check if we already have a mesh
            if (renderer == null) {
                renderer = new VoxelRenderer(new Index(detailLevel, x, y, z), control);
            } else if (!force) {
                return;
            }

            // We should generate a mesh
            GenMeshJob updateJob = new GenMeshJob(this, control, detailLevel);
            updateJob.setOffset(x, y, z);
            control.enqueueUpdate(updateJob);
        }
        public void setToHeightmap(byte detailLevel, int x, int y, int z, ref float[,] map, byte material, OcTree control)
        {
            if (detailLevel <= CHILD_COUNT_POWER) {
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi) {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi) {
                        for (int yi = 0; yi < CHILD_DIMENSION; ++yi) {
                            if (yi + y >= map[x + xi, z + zi])
                                break;
                            else if (material == byte.MaxValue) {
                                children[xi, yi, zi] = Voxel.empty;
                            } else {
                                if (yi + y >= map[x + xi, z + zi] - 1) {
                                    byte opacity = (byte)((map[x + xi, z + zi] - yi - y) * byte.MaxValue);
                                    if (opacity > control.isoLevel || children[xi, yi, zi].averageOpacity() <= opacity)
                                        children[xi, yi, zi] = new Voxel(material, opacity);
                                } else {
                                    children[xi, yi, zi] = new Voxel(material, byte.MaxValue);
                                }
                            }
                        }
                    }
                }
            } else {
                int multiplier = (1 << (detailLevel - CHILD_COUNT_POWER));
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi) {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi) {
                        int xMax = x + (xi + 1) * multiplier;
                        int zMax = z + (zi + 1) * multiplier;
                        float yMin = float.MaxValue;
                        float yMax = 0;
                        for (int xPos = x + xi * multiplier; xPos < xMax; ++xPos) {
                            for (int zPos = z + zi * multiplier; zPos < zMax; ++zPos) {
                                if (map[xPos, zPos] < yMin) yMin = map[xPos, zPos];
                                if (map[xPos, zPos] > yMax) yMax = map[xPos, zPos];
                            }
                        }

                        int firstUnsolidBlock = Mathf.Min(((int)(yMin - y)) / multiplier, CHILD_DIMENSION);
                        int lastUnsolidBlock = Mathf.Min(((int)(yMax - y)) / multiplier, CHILD_DIMENSION - 1);
                        int yi = 0;
                        for (; yi < firstUnsolidBlock; ++yi) {
                            if (material == byte.MaxValue)
                                children[xi, yi, zi] = Voxel.empty;
                            else
                                children[xi, yi, zi] = new Voxel(material, byte.MaxValue);
                        }
                        if (lastUnsolidBlock < 0) continue;
                        for (; yi <= lastUnsolidBlock; ++yi) {
                            if (children[xi, yi, zi].GetType() == typeof(Voxel))
                                children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
                            ((VoxelBlock)children[xi, yi, zi]).setToHeightmap((byte)(detailLevel - CHILD_COUNT_POWER), x + xi * multiplier, y + yi * multiplier, z + zi * multiplier, ref map, material, control);
                        }
                    }
                }
            }
            control.dirty = true;
        }
 public VoxelBlock expand(uint x, uint y, uint z)
 {
     if (children[x, y, z].GetType() == typeof(Voxel))
         children[x, y, z] = new VoxelBlock((Voxel)children[x, y, z]);
     return (VoxelBlock)children[x, y, z];
 }
Example #20
0
 public GenMeshJob(VoxelBlock block, VoxelTree control, byte detailLevel)
 {
     this.block       = block;
     this.control     = control;
     this.detailLevel = detailLevel;
 }
Example #21
0
        public void setToHeightmap(byte detailLevel, int x, int y, int z, ref float[,] map, byte[,] mats, Tree control)
        {
            if (detailLevel <= CHILD_COUNT_POWER)
            {
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi)
                {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi)
                    {
                        for (int yi = 0; yi < CHILD_DIMENSION; ++yi)
                        {
                            if (yi + y >= map[x + xi, z + zi])
                            {
                                break;
                            }
                            else if (yi + y >= map[x + xi, z + zi] - 1)
                            {
                                if (mats[x + xi, z + zi] == byte.MaxValue)
                                {
                                    children[xi, yi, zi] = Voxel.empty;
                                }
                                else
                                {
                                    children[xi, yi, zi] = new Voxel(mats[x + xi, z + zi], (byte)((map[x + xi, z + zi] - yi - y) * byte.MaxValue));
                                }
                            }
                            else
                            {
                                if (mats[x + xi, z + zi] == byte.MaxValue)
                                {
                                    children[xi, yi, zi] = Voxel.empty;
                                }
                                else
                                {
                                    children[xi, yi, zi] = new Voxel(mats[x + xi, z + zi], byte.MaxValue);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                int multiplier = (1 << (detailLevel - CHILD_COUNT_POWER));
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi)
                {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi)
                    {
                        int   xMax = x + (xi + 1) * multiplier;
                        int   zMax = z + (zi + 1) * multiplier;
                        float yMin = float.MaxValue;
                        float yMax = 0;
                        bool  multipleMaterials = false;
                        byte  material          = mats[x, z];
                        for (int xPos = x + xi * multiplier; xPos < xMax; ++xPos)
                        {
                            for (int zPos = z + zi * multiplier; zPos < zMax; ++zPos)
                            {
                                if (map[xPos, zPos] < yMin)
                                {
                                    yMin = map[xPos, zPos];
                                }
                                if (map[xPos, zPos] > yMax)
                                {
                                    yMax = map[xPos, zPos];
                                }
                                if (mats[xPos, zPos] != material)
                                {
                                    multipleMaterials = true;
                                }
                            }
                        }

                        if (multipleMaterials)
                        {
                            yMin = 0;
                        }
                        int firstUnsolidBlock = Mathf.Min(((int)(yMin - y)) / multiplier, CHILD_DIMENSION);
                        int lastUnsolidBlock  = Mathf.Min(((int)(yMax - y)) / multiplier, CHILD_DIMENSION - 1);
                        int yi = 0;
                        for (; yi < firstUnsolidBlock; ++yi)
                        {
                            if (mats[x + xi * multiplier, z + zi * multiplier] == byte.MaxValue)
                            {
                                children[xi, yi, zi] = Voxel.empty;
                            }
                            else
                            {
                                children[xi, yi, zi] = new Voxel(mats[x + xi * multiplier, z + zi * multiplier], byte.MaxValue);
                            }
                        }
                        if (lastUnsolidBlock < 0)
                        {
                            continue;
                        }
                        for (; yi <= lastUnsolidBlock; ++yi)
                        {
                            VoxelBlock newChild = new VoxelBlock();
                            newChild.setToHeightmap((byte)(detailLevel - CHILD_COUNT_POWER), x + xi * multiplier, y + yi * multiplier, z + zi * multiplier, ref map, mats, control);
                            children[xi, yi, zi] = newChild;
                        }
                    }
                }
            }
            control.dirty = true;
        }
Example #22
0
        public void setToHeightmap(byte detailLevel, int x, int y, int z, ref float[,] map, byte material, Tree control)
        {
            if (detailLevel <= CHILD_COUNT_POWER)
            {
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi)
                {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi)
                    {
                        for (int yi = 0; yi < CHILD_DIMENSION; ++yi)
                        {
                            if (yi + y >= map[x + xi, z + zi])
                            {
                                break;
                            }
                            else if (material == byte.MaxValue)
                            {
                                children[xi, yi, zi] = Voxel.empty;
                            }
                            else
                            {
                                if (yi + y >= map[x + xi, z + zi] - 1)
                                {
                                    byte opacity = (byte)((map[x + xi, z + zi] - yi - y) * byte.MaxValue);
                                    if (opacity > control.isoLevel || children[xi, yi, zi].averageOpacity() <= opacity)
                                    {
                                        children[xi, yi, zi] = new Voxel(material, opacity);
                                    }
                                }
                                else
                                {
                                    children[xi, yi, zi] = new Voxel(material, byte.MaxValue);
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                int multiplier = (1 << (detailLevel - CHILD_COUNT_POWER));
                for (int xi = 0; xi < CHILD_DIMENSION; ++xi)
                {
                    for (int zi = 0; zi < CHILD_DIMENSION; ++zi)
                    {
                        int   xMax = x + (xi + 1) * multiplier;
                        int   zMax = z + (zi + 1) * multiplier;
                        float yMin = float.MaxValue;
                        float yMax = 0;
                        for (int xPos = x + xi * multiplier; xPos < xMax; ++xPos)
                        {
                            for (int zPos = z + zi * multiplier; zPos < zMax; ++zPos)
                            {
                                if (map[xPos, zPos] < yMin)
                                {
                                    yMin = map[xPos, zPos];
                                }
                                if (map[xPos, zPos] > yMax)
                                {
                                    yMax = map[xPos, zPos];
                                }
                            }
                        }

                        int firstUnsolidBlock = Mathf.Min(((int)(yMin - y)) / multiplier, CHILD_DIMENSION);
                        int lastUnsolidBlock  = Mathf.Min(((int)(yMax - y)) / multiplier, CHILD_DIMENSION - 1);
                        int yi = 0;
                        for (; yi < firstUnsolidBlock; ++yi)
                        {
                            if (material == byte.MaxValue)
                            {
                                children[xi, yi, zi] = Voxel.empty;
                            }
                            else
                            {
                                children[xi, yi, zi] = new Voxel(material, byte.MaxValue);
                            }
                        }
                        if (lastUnsolidBlock < 0)
                        {
                            continue;
                        }
                        for (; yi <= lastUnsolidBlock; ++yi)
                        {
                            if (children[xi, yi, zi].GetType() == typeof(Voxel))
                            {
                                children[xi, yi, zi] = new VoxelBlock((Voxel)children[xi, yi, zi]);
                            }
                            ((VoxelBlock)children[xi, yi, zi]).setToHeightmap((byte)(detailLevel - CHILD_COUNT_POWER), x + xi * multiplier, y + yi * multiplier, z + zi * multiplier, ref map, material, control);
                        }
                    }
                }
            }
            control.dirty = true;
        }