rendered paste bodyusing 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);
}
}
}