// Use this for initialization void Start() { float voxelSize = 1.0f; int size = 33; Array3 <Voxel> voxels = WorldGenerator.CreateVoxels(size, 0, voxelSize, Vector3.zero); MeshData data = MarchingCubes.CalculateMeshData(voxels, voxelSize); data.CalculateNormals(); Mesh mesh = null; if (data != null) { mesh = data.CreateMesh(); } ChunkObject obj = SplitManager.GetObject(); obj.ov.shouldDraw = true; obj.mr.material = mat; obj.mf.mesh = mesh; Vector3 center = Vector3.one * (size - 1) / 2.0f; Bounds area = new Bounds(center, Vector3.one * voxelSize * (size - 1)); obj.ov.init(0, 0, center, area, null, Color.red); }
// takes in voxel array and MeshData vertices and returns array of mesh normals public static Vector3[] CalculateSmoothNormals(Array3 <sbyte> voxels, float voxelSize, Vector3[] verts) { // calculates the normal of each voxel. If you have a 3d array of data // the normal is the derivitive of the x, y and z axis. // normally you need to flip the normal (*-1) but it is not needed in this case. int size = voxels.size; Vector3[][][] normals = Init3DArray <Vector3>(size); // TODO reuse this for (int x = 2; x < size - 2; x++) { for (int y = 2; y < size - 2; y++) { for (int z = 2; z < size - 2; z++) { float dx = voxels[x + 1, y, z] - voxels[x - 1, y, z]; float dy = voxels[x, y + 1, z] - voxels[x, y - 1, z]; float dz = voxels[x, y, z + 1] - voxels[x, y, z - 1]; normals[x][y][z] = Vector3.Normalize(new Vector3(dx, dy, dz) / 128.0f * voxelSize); } } } int numVerts = verts.Length; Vector3[] meshNorms = new Vector3[numVerts]; for (int i = 0; i < numVerts; ++i) { meshNorms[i] = TriLerpNormals(verts[i] / voxelSize, normals); } return(meshNorms); }
public static MeshData GenLodCell(Array3 <sbyte> chunk, int lod) { MeshBuilder mesh = new MeshBuilder(); sbyte[] density = new sbyte[8]; int size = chunk.size; for (int x = 0; x < size; ++x) { for (int y = 0; y < size; ++y) { for (int z = 0; z < size; ++z) { // send this cell the 8 density values at its corners for (int i = 0; i < 8; ++i) { density[i] = chunk[ x + Tables.vertexOffset[i, 0], y + Tables.vertexOffset[i, 1], z + Tables.vertexOffset[i, 2]]; } //PolygonizeCell(new Vector3i(x, y, z), mesh, lod); } } } return(mesh.ToMeshData()); }
public Chunk(Vector3 worldPosition) { World = worldPosition; Bounds = new AxisAlignedBoundingBox(worldPosition, worldPosition + Dimensions); _blocks = new Array3 <Block>(Width, Height, Depth); }
void Start() { miner = GameObject.Find("Player").GetComponent <VoxelMining>(); Array3 <Voxel> voxels = WorldGenerator.CreateVoxels(33, 0, 1.0f, Vector3.zero); //Array3<Voxel> voxels = WorldGenerator.CreateVoxels(64, 0, 1.0f, Vector3.zero); MeshData data = MarchingCubes.CalculateMeshData(voxels, 1.0f); Mesh mesh = data.CreateMesh(); go = SplitManager.GetObject(); go.mr.enabled = false; go.mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; go.mf.sharedMesh = mesh; go.mr.material = testMat; MeshData data2 = MarchingTetrahedra.CalculateMeshData(voxels, 1.0f); data2.CalculateSharedNormals(); Mesh mesh2 = data2.CreateMesh(); go2 = SplitManager.GetObject(); go2.mf.sharedMesh = mesh2; go2.mr.material = testMat; go2.mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.TwoSided; miner.forceDrawChunk = go2; }
private static UIVertex PickupUIVertexFromTriangle(Vector2 pickupPosition, VerticesOffset vertexPack, Vector2[] vertices2d) { var inverseArea = 1.0f / GetAreaOfTriangle(vertices2d[0], vertices2d[1], vertices2d[2]); var vertices = vertexPack.GetEnumerable(); var weights = new Array3 <float>(GetAreaOfTriangle(pickupPosition, vertices2d[1], vertices2d[2]) * inverseArea , GetAreaOfTriangle(vertices2d[0], pickupPosition, vertices2d[2]) * inverseArea , GetAreaOfTriangle(vertices2d[0], vertices2d[1], pickupPosition) * inverseArea ).GetEnumerable(); var result = WeightedAverage(vertices, weights); return(result); }
private static Vector3 Interp(Vector3 v0, Vector3 v1, Vector3i p0, Vector3i p1, Array3 <sbyte> voxels) { sbyte s0 = voxels[p0]; sbyte s1 = voxels[p1]; int t = (s1 << 8) / (s1 - s0); int u = 0x0100 - t; if ((t & 0x00ff) == 0) { // The generated vertex lies at one of the corners so there // is no need to subdivide the interval. if (t == 0) { return(v1); } return(v0); } else { Vector3 vm = (v0 + v1) / 2; Vector3i pm = (p0 + p1) / 2; sbyte sm = voxels[pm]; // Determine which of the sub-intervals that contain // the intersection with the isosurface. if (Sign(s0) != Sign(sm)) { v1 = vm; p1 = pm; s1 = sm; } else { v0 = vm; p0 = pm; s0 = sm; } t = (s1 << 8) / (s1 - s0); u = 0x0100 - t; return(v0 * t * ONE_OVER_256 + v1 * u * ONE_OVER_256); } }
public Chunk(World world, ChunkPosition position, IEnvironmentGenerator environmentGenerator, IChunkRenderer renderer, BlockPrototypeMap prototypeMap) { Position = position; this.world = world; this.environmentGenerator = environmentGenerator; this.renderer = renderer; blockArray = new BlockArray(prototypeMap, XDimension, YDimension, ZDimension); lightArray = new Array3<byte>(XDimension, YDimension, ZDimension); OriginInWorld = new BlockPosition(Position, new RelativeBlockPosition(0, 0, 0)); neighborhoodPositions = new[] { Position, Position.Left, Position.Right, Position.Front, Position.Back }; }
public override T this[int x, int y, int z] { get { if (x < 0 || y < 0 || z < 0) { return(default(T)); } Vector3i v = new Vector3i(x / chunkSize, y / chunkSize, z / chunkSize) * chunkSize; Array3 <T> a; if (data.TryGetValue(v, out a)) { return(a[x % chunkSize, y % chunkSize, z % chunkSize]); } else { return(default(T)); } } set { Vector3i v = new Vector3i(x / chunkSize, y / chunkSize, z / chunkSize) * chunkSize; Array3 <T> a; if (!data.ContainsKey(v)) { a = new Array3 <T>(chunkSize, v); data[v] = a; } else { a = data[v]; } a[x % chunkSize, y % chunkSize, z % chunkSize] = value; } }
public static MeshData CalculateMeshData(Array3 <Voxel> voxels, float voxelSize) { List <Vector3> verts = new List <Vector3>(); List <int> tris = new List <int>(); sbyte[] density = new sbyte[8]; int end = voxels.size - 1; for (int z = 0; z < end; ++z) { for (int y = 0; y < end; ++y) { for (int x = 0; x < end; ++x) { for (int i = 0; i < 8; ++i) { density[i] = voxels[ x + vertexOffset[i][0], y + vertexOffset[i][1], z + vertexOffset[i][2]].density; } March(x, y, z, density, verts, tris); } } } MeshData md = new MeshData(verts.ToArray(), tris.ToArray()); List <Color32> colors = new List <Color32>(); for (int i = 0; i < verts.Count; ++i) { colors.Add(new Color32(216, 202, 168, 255)); } md.colors = colors.ToArray(); return(md); }
public MeshData GenerateMesh(bool createVoxels) { // so while SIZE is 16, which means theres 16 cells/blocks in grid // you need 17 values to be able to construct those blocks // (think of 17 points in a grid and the blocks are the 16 spaces in between) // if smoothing then need a buffer of 2 around (front and back so +4) for smoothing and normal calculation // (so mesh goes from 2-19 basically (0, 1, 20, 21) are not visible in final result) #if (SMOOTH_SHADING) if (createVoxels) { voxels = WorldGenerator.CreateVoxels(SIZE + 5, depth, voxelSize, pos); } MeshData data = MarchingCubes.CalculateMeshData(voxels, voxelSize, 2, 2); data.CalculateVertexSharing(); //Simplification simp = new Simplification(data.vertices, data.triangles); //data.normals = VoxelUtils.CalculateSmoothNormals(voxels, voxelSize, data.vertices); //data.SplitEdgesCalcSmoothness(); data.CalculateSharedNormals(); // todo figure out why this doesnt make it smoothed... #else if (createVoxels) { voxels = WorldGenerator.CreateVoxels(SIZE + 1, depth, voxelSize, worldPos); } //if (!needsMesh) { // return null; //} //MeshData data = MarchingTetrahedra.CalculateMeshData(voxels, voxelSize); MeshData data = MarchingCubes.CalculateMeshData(voxels, voxelSize); data.CalculateNormals(); #endif //data.CalculateColorsByDepth(depth); return(data); }
public BackwardUpdates(ref Vp9BackwardUpdates counts) { InterModeCounts = new Array7 <Array3 <Array2 <uint> > >(); for (int i = 0; i < 7; i++) { InterModeCounts[i][0][0] = counts.InterMode[i][2]; InterModeCounts[i][0][1] = counts.InterMode[i][0] + counts.InterMode[i][1] + counts.InterMode[i][3]; InterModeCounts[i][1][0] = counts.InterMode[i][0]; InterModeCounts[i][1][1] = counts.InterMode[i][1] + counts.InterMode[i][3]; InterModeCounts[i][2][0] = counts.InterMode[i][1]; InterModeCounts[i][2][1] = counts.InterMode[i][3]; } YModeCounts = counts.YMode; UvModeCounts = counts.UvMode; PartitionCounts = counts.Partition; SwitchableInterpsCount = counts.SwitchableInterp; IntraInterCount = counts.IntraInter; CompInterCount = counts.CompInter; SingleRefCount = counts.SingleRef; CompRefCount = counts.CompRef; Tx32x32 = counts.Tx32x32; Tx16x16 = counts.Tx16x16; Tx8x8 = counts.Tx8x8; MbSkipCount = counts.Skip; Joints = counts.Joints; Sign = counts.Sign; Classes = counts.Classes; Class0 = counts.Class0; Bits = counts.Bits; Class0Fp = counts.Class0Fp; Fp = counts.Fp; Class0Hp = counts.Class0Hp; Hp = counts.Hp; CoefCounts = counts.Coef; EobCounts = counts.EobBranch; }
public static void SetupDstPlanes( ref Array3 <MacroBlockDPlane> planes, ref Surface src, int miRow, int miCol) { Span <ArrayPtr <byte> > buffers = stackalloc ArrayPtr <byte> [Constants.MaxMbPlane]; buffers[0] = src.YBuffer; buffers[1] = src.UBuffer; buffers[2] = src.VBuffer; Span <int> strides = stackalloc int[Constants.MaxMbPlane]; strides[0] = src.Stride; strides[1] = src.UvStride; strides[2] = src.UvStride; int i; for (i = 0; i < Constants.MaxMbPlane; ++i) { ref MacroBlockDPlane pd = ref planes[i]; SetupPredPlanes(ref pd.Dst, buffers[i], strides[i], miRow, miCol, Ptr <ScaleFactors> .Null, pd.SubsamplingX, pd.SubsamplingY); }
/// <summary> /// Create a new instance of <see cref="GamepadStateSnapshot"/>. /// </summary> /// <param name="joysticksState">The joysticks state</param> /// <param name="buttonsState">The buttons state</param> public GamepadStateSnapshot(Array3 <Array2 <float> > joysticksState, Array28 <bool> buttonsState) { _joysticksState = joysticksState; _buttonsState = buttonsState; }
// size is length of arrays // depth is octree depth // voxelSize is how big each voxel should be // radius is radius of planet // position is starting position of quadtree public static Array3 <Voxel> CreateVoxels( int size, int depth, float voxelSize, Vector3 pos) { //float[][][] voxels = VoxelUtils.Init3DArray<float>(size); // Vector3i is for some hash lookup shit i think if i wanted to do // like hashset<Vector3i, Array3?) Array3 <Voxel> voxels = new Array3 <Voxel>(size, Vector3i.Zero); //int s = (depth == 0) ? 0 : 1; //s = 0; // temp until figure out data inheritance //for (int x = s; x < size; x += s + 1) { // for (int y = s; y < size; y += s + 1) { // for (int z = s; z < size; z += s + 1) { // Vector3 worldPos = new Vector3(x, y, z) * voxelSize + pos; // voxels[x, y, z] = Density.Eval(worldPos); // //voxels[x,y,z] = (sbyte)Mathf.Clamp(Density.Eval(worldPos), -128.0f, 127.0f); // } // } //} // figure this out more.. // add command to regenerate with different levels here so you can see changes in realtime // to better understand why it isnt working with r as voxelSize / 2.0f // sbyte goes from -128 to 127 (so -128, -1 and 0 to 127 should be range) int x, y, z; for (z = 0; z < size; ++z) { for (y = 0; y < size; ++y) { for (x = 0; x < size; ++x) { Vector3 worldPos = new Vector3(x, y, z) * voxelSize + pos; voxels[x, y, z] = Density.EvalBigPlanet(worldPos, voxelSize); } } } // could incorporate into loops above probably (this is probably microoptimization tho i dunno) //// figure out if chunk will have a mesh //bool set = false; //bool positive = false; //for (x = 0; x < size; ++x) { // for (y = 0; y < size; ++y) { // for (z = 0; z < size; ++z) { // if (!set) { // positive = voxels[x, y, z] >= MarchingCubes.isoLevel; // set = true; // }else if((positive && voxels[x,y,z] < MarchingCubes.isoLevel)|| // (!positive && voxels[x,y,z] >= MarchingCubes.isoLevel)) { // needsMesh = true; // return voxels; // } // } // } //} //needsMesh = false; return(voxels); }
public BlockArray(BlockPrototypeMap prototypeMap, int xDimension, int yDimension, int zDimension) { this.prototypeMap = prototypeMap; blockIndexes = new Array3<byte>(xDimension, yDimension, zDimension); }
public static byte GetPredProbSegId(ref Array3 <byte> segPredProbs, ref MacroBlockD xd) { return(segPredProbs[xd.GetPredContextSegId()]); }
// start and end are used to add padding before and after basically public static MeshData CalculateMeshData(Array3 <Voxel> voxels, float voxelSize, int start = 0, int end = 0) { List <Vector3> verts = new List <Vector3>(); List <Color32> colors = new List <Color32>(); // used to be static but now in here so can be multithreaded Vector3[] edgeVertices = new Vector3[12]; // later should do different materials and stuff using seperate submeshes or multimaterial on same mesh i dunno // if want to have cool shiny ore!!!! Color32[] edgeColors = new Color32[12]; Voxel[] cube = new Voxel[8]; // temp storage for 8 voxels corners of cube int endLen = voxels.size - 1 - end; // voxel array is always cube int materialColorLength = materialColors.Length; int x, y, z, i; for (z = start; z < endLen; z++) { for (y = start; y < endLen; y++) { for (x = start; x < endLen; x++) { // get density values of 8 corners for each cube for (i = 0; i < 8; i++) { cube[i] = voxels[ x + vertexOffset[i, 0], y + vertexOffset[i, 1], z + vertexOffset[i, 2]]; } //MarchCube(new Vector4(x, y, z, voxelSize), density, block, verts, colors, edgeVertices, edgeColors); int flagIndex = 0; float offset = 0.0f; //Find which vertices are inside of the surface and which are outside // positive density is inside, negative is outside for (i = 0; i < 8; i++) { if (cube[i].density >= ISOLEVEL) { flagIndex |= 1 << i; } } //Find which edges are intersected by the surface int edgeFlags = cubeEdgeFlags[flagIndex]; //If the cube is entirely inside or outside of the surface, then there will be no intersections if (edgeFlags == 0) { continue; } //Check each edge to see if it has a point of intersection with the surface for (i = 0; i < 12; i++) { //if there is an intersection on this edge if ((edgeFlags & (1 << i)) != 0) { // find approximate point of intersection of the surface between two points float v1 = cube[edgeConnection[i, 0]].density; float v2 = cube[edgeConnection[i, 1]].density; float delta = (v2 - v1); offset = (delta == 0.0f) ? 0.5f : (ISOLEVEL - v1) / delta; edgeVertices[i].x = x + (vertexOffset[edgeConnection[i, 0], 0] + offset * edgeDirection[i, 0]); edgeVertices[i].y = y + (vertexOffset[edgeConnection[i, 0], 1] + offset * edgeDirection[i, 1]); edgeVertices[i].z = z + (vertexOffset[edgeConnection[i, 0], 2] + offset * edgeDirection[i, 2]); edgeVertices[i] *= voxelSize; // corresponds to voxel size byte m1 = cube[edgeConnection[i, 0]].material; byte m2 = cube[edgeConnection[i, 1]].material; if (m1 < materialColorLength && m2 < materialColorLength) { Color32 c = materialColors[m1]; edgeColors[i] = Color32.Lerp(materialColors[m1], materialColors[m2], offset); } else { edgeColors[i] = new Color32(255, 0, 255, 255); // magenta error color I guess? lols } } } //Save the triangles that were found. There can be up to five per cube for (i = 0; i < 5; i++) { if (triangleConnectionTable[flagIndex, 3 * i] < 0) { break; } int t1 = triangleConnectionTable[flagIndex, 3 * i]; int t2 = triangleConnectionTable[flagIndex, 3 * i + 1]; int t3 = triangleConnectionTable[flagIndex, 3 * i + 2]; verts.Add(edgeVertices[t1]); verts.Add(edgeVertices[t2]); verts.Add(edgeVertices[t3]); colors.Add(edgeColors[t1]); colors.Add(edgeColors[t2]); colors.Add(edgeColors[t3]); } //PolygonizeCell(new Vector3i(x, y, z), density, verts); //TransvoxelExtractor.PolygonizeRegularCell(new Vector3i(x, y, z), voxels, verts, tris); } } } MeshData md = new MeshData(verts.ToArray()); md.colors = colors.ToArray(); return(md); //return new MeshData(verts.ToArray(), tris.ToArray()); }
// pos is xyz position of cell and density is values at corners public static void PolygonizeRegularCell(Vector3i pos, Array3 <sbyte> voxels, List <Vector3> verts, List <int> indices) { byte dirMask = (byte)((pos.x > 0 ? 1 : 0) | ((pos.y > 0 ? 1 : 0) << 1) | ((pos.z > 0 ? 1 : 0) << 2)); //byte near = 0; // compute which six faces of the block that vertex is near (in boundary cell) // skip this for now since no transitions Vector3i[] corners = Tables.CornerIndex; for (int i = 0; i < corners.Length; ++i) { corners[i] += pos; } sbyte[] density = new sbyte[] { voxels[corners[0]], voxels[corners[1]], voxels[corners[2]], voxels[corners[3]], voxels[corners[4]], voxels[corners[5]], voxels[corners[6]], voxels[corners[7]] }; uint caseCode = (uint)( ((density[0] >> 7) & 0x01) | ((density[1] >> 6) & 0x02) | ((density[2] >> 5) & 0x04) | ((density[3] >> 4) & 0x08) | ((density[4] >> 3) & 0x10) | ((density[5] >> 2) & 0x20) | ((density[6] >> 1) & 0x40) | (density[7] & 0x80)); var c = Tables.RegularCellClass[caseCode]; var data = Tables.RegularCellData[c]; byte numTris = (byte)data.GetTriangleCount(); byte numVerts = (byte)data.GetVertexCount(); int[] localVertexMapping = new int[12]; // generate vertex positions by interpolating along // each of the edges that intersect the isosurface for (int i = 0; i < numVerts; ++i) { ushort edgeCode = Tables.RegularVertexData[caseCode][i]; byte v0 = HiNibble((byte)(edgeCode & 0xFF)); byte v1 = LoNibble((byte)(edgeCode & 0xFF)); Vector3i p0 = corners[v0]; Vector3i p1 = corners[v1]; int d0 = voxels[p0]; int d1 = voxels[p1]; Debug.Assert(v0 < v1); int t = (d1 << 8) / (d1 - d0); int u = 0x0100 - t; float t0 = t * ONE_OVER_256; float t1 = u * ONE_OVER_256; if ((t & 0x00ff) != 0) { // vertex lies in the interior of the edge byte dir = HiNibble((byte)(edgeCode >> 8)); byte idx = LoNibble((byte)(edgeCode >> 8)); //bool present = (dir & dirMask) == dir; localVertexMapping[i] = verts.Count; Vector3 pi = Interp(p0.ToVector3(), p1.ToVector3(), p0, p1, voxels); verts.Add(pi); } else if (true || t == 0 && v1 == 7) { // check if this is right Vector3 pi = new Vector3( p0.x * t0 + p1.x * t1, p0.y * t0 + p1.y * t1, p0.z * t0 + p1.z * t1); localVertexMapping[i] = verts.Count; verts.Add(pi); } } for (int t = 0; t < numTris; ++t) { for (int i = 0; i < 3; ++i) { indices.Add(localVertexMapping[data.GetIndices()[t * 3 + i]]); } } }