All pastes #2066394 Raw Edit

Unnamed

public text v1 · immutable
#2066394 ·published 2011-05-21 23:16 UTC
rendered paste body
using System;
using System.Drawing;

namespace Voxelcat
{
	public class Frustum
	{
		public double lx, ly, mx, my;
		public double Width { get { return mx - lx; } }
		public double Height { get { return my - ly; } }
		public double SpreadFactor = 1.05;
		public double Z = 1.0;
		
		public Frustum()
		{
			lx = -Blitman.Width / 2.0;
			ly = -Blitman.Height / 2.0;
			mx = Blitman.Width / 2.0;
			my = Blitman.Height / 2.0;
		}
		
		public void Advance(double z)
		{
			Z += z;
			double hz = z * (1.0 + ((SpreadFactor - 1.0) / 2.0));
			lx *= hz;
			ly *= hz;
			mx *= hz;
			my *= hz;
		}
		
	}
	
	public interface VoxelStructure 
	{
		int TryGetVoxelInRayPath(double rsx, double rsy, double rsz, double rfx, double rfy, double rfz);
	}
	
	public class Octree : VoxelStructure
	{
		// 0 = front top left, 1 = front top right, 2 = front bottom left, 3 = front bottom right,
		// 4 = back top left, ... etc.
		public VoxelStructure[] Friends = new VoxelStructure[8];
		// dimensions MUST BE POSITIVELY ALONG AXES!  m_ always greater than l_.
		public double lx, ly, lz, mx, my, mz;
		
		public Octree(double olx, double oly, double olz, double omx, double omy, double omz)
		{
			this.lx = (olx < omx ? olx : omx); this.ly = (oly < omy ? oly : omy); this.lz = (olz < omz ? olz : omz);
			this.mx = (omx > olx ? omx : olx); this.my = (omy > oly ? omy : oly); this.mz = (omz > olz ? omz : olz);
		}
		
		public int TryGetVoxelInRayPath(double rsx, double rsy, double rsz, double rfx, double rfy, double rfz)
		{
			// Input ray MUST BE GOING POSITIVELY ALONG AXES! rf_ always greater than rs_.
			// if, for every dimension, ray contains octree or octree contains ray:
			if ((rsz <= lz) && (rfz >= mz) || (lz < rsz) && (mz > rfz))
				if ((rsy <= ly) && (rfy >= my) || (ly < rsy) && (my > rfy))
					if ((rsx <= lx) && (rfx >= mx) || (lx < rsx) && (mx > rfx))
					{
						// ok, so we should search internally then.
						foreach (VoxelStructure oct in Friends)
						{
							if (oct == null)
								continue;
							int c = oct.TryGetVoxelInRayPath(rsx, rsy, rsz, rfx, rfy, rfz);
							if (c != 0)
								return c;
						}
						
						// crap accuracy has screwed us over, or just a sparse octree.
						//Console.WriteLine(string.Format("crap accuracy screwed us over in octree with bounds ({0},{1},{2}::{3},{4},{5})"));
						return 0;  // TODO: return red?
					}
			
			return 0;
		}
	}
	
	public class Voxel : VoxelStructure
	{
		public double lx, ly, lz, mx, my, mz;
		public int c;
		
		public Voxel(double olx, double oly, double olz, double omx, double omy, double omz, int oc)
		{
			this.lx = olx; this.ly = oly; this.lz = olz;
			this.mx = omx; this.my = omy; this.mz = omz;
			this.c = oc;
		}
			
		#region VoxelStructure implementation
		public int TryGetVoxelInRayPath(double rsx, double rsy, double rsz, double rfx, double rfy, double rfz)
		{
			if ((rsz <= lz) && (rfz >= mz) || (lz < rsz) && (mz > rfz))
				if ((rsy <= ly) && (rfy >= my) || (ly < rsy) && (my > rfy))
					if ((rsx <= lx) && (rfx >= mx) || (lx < rsx) && (mx > rfx))
						return c;
			return 0;
		}
		#endregion
	}
	
	
	
	public class SimpleVox
	{
		const double maxz = 100.0;
		VoxelStructure world;
		
		private void SubconstructVoxelsForOctree(Octree oct)
		{
			double hx = (oct.lx + oct.mx) / 2.0;
			double hy = (oct.ly + oct.my) / 2.0;
			double hz = (oct.lz + oct.mz) / 2.0;
			oct.Friends[0] = new Voxel(oct.lx ,oct.ly , oct.lz, hx, hy, hz, 0);
			oct.Friends[1] = new Voxel(hx , oct.ly, oct.lz, oct.mx, hy, hz, 0);
			oct.Friends[2] = new Voxel(oct.lx , hy, oct.lz, hx, oct.my, hz, 0);
			oct.Friends[3] = new Voxel(hx, hy, oct.lz, oct.mx, oct.my, hz, 0);
			oct.Friends[4] = new Voxel(oct.lx ,oct.ly , hz, hx, hy, oct.mz, 0);
			oct.Friends[5] = new Voxel(hx , oct.ly, hz, oct.mx, hy, oct.mz, 0);
			oct.Friends[6] = new Voxel(oct.lx , hy, hz, hx, oct.my, oct.mz, 0);
			oct.Friends[7] = new Voxel(hx, hy, hz, oct.mx, oct.my, oct.mz, 0);
			
		}
		
		private void SubconstructOctree(Octree oct)
		{
			double hx = (oct.lx + oct.mx) / 2.0;
			double hy = (oct.ly + oct.my) / 2.0;
			double hz = (oct.lz + oct.mz) / 2.0;
			oct.Friends[0] = new Octree(oct.lx ,oct.ly , oct.lz, hx, hy, hz);
			oct.Friends[1] = new Octree(hx , oct.ly, oct.lz, oct.mx, hy, hz);
			oct.Friends[2] = new Octree(oct.lx , hy, oct.lz, hx, oct.my, hz);
			oct.Friends[3] = new Octree(hx, hy, oct.lz, oct.mx, oct.my, hz);
			//oct.Friends[4] = new Octree(oct.lx ,oct.ly , hz, hx, hy, oct.mz);
			//oct.Friends[5] = new Octree(hx , oct.ly, hz, oct.mx, hy, oct.mz);
			//oct.Friends[6] = new Octree(oct.lx , hy, hz, hx, oct.my, oct.mz);
			//oct.Friends[7] = new Octree(hx, hy, hz, oct.mx, oct.my, oct.mz);
			
		}
		
		public SimpleVox ()
		{
			Octree oct = new Octree(0.0, 0.0, 1.0, 1.0, 1.0, 2.0);
			SubconstructOctree(oct);
			for (int i = 0; i < 4; i++)
			{
				SubconstructVoxelsForOctree((Octree)oct.Friends[i]);
				((Voxel)(((Octree)oct.Friends[i]).Friends[3-i])).c = int.MaxValue;
				for (int y = 0; y < 8; y++)
					if (y != 3-i)
						(((Octree)oct.Friends[i])).Friends[y] = null;
			}
			world = oct;
			
		}
		
		public int[] Render(int w, int h)
		{
			int[] results = new int[w * h];
			double sy = 1.0/(2*h);
			double sx = 1.0/(2*w);
			
			double mz = 5.0;
			double spr = 0.00;
			
			for (int iy = 0; iy < h; iy++)
				for (int ix = 0; ix < w; ix++)
				{
					double x = ix * (1.0/w) + sx;
					double y = iy * (1.0/h) + sy;
				
					int i =(int)(iy * w + ix) ;
					results[i] = world.TryGetVoxelInRayPath(x, y, 0.0, x + x * spr, y  + y* spr, mz);
				}	
			return results;
		}
		
		
		
		public bool voxExistsAt(double x, double y, double z)
		{
			return (x > 0.5 && x < 0.7 && y > 0.5 && y < 0.7);
		}
	}
}