public static void GetBlockMesh(Block block, MeshFilter filter) { var blockData = JobController.instance.blockData; BlockData bd = blockData[block.type]; var vertices = Pools.v3N.Get(); var normals = Pools.v3N.Get(); var uvs = Pools.v3N.Get(); var uv2s = Pools.v3N.Get(); var colors = Pools.c32N.Get(); var triangles = Pools.intN.Get(); NativeMeshData data = new NativeMeshData(vertices, normals, uvs, uv2s, colors, triangles, faceList); const int x = 1; const int y = 1; const int z = 1; blockArray.c[x + z * S + y * S * S] = block; ushort light = bd.light; if (light == 0) { light = ushort.MaxValue; } lightArray.c[x + z * S + y * S * S] = new Light { torch = light }; lightArray.c[x - 1 + z * S + y * S * S] = new Light { torch = light }; lightArray.c[x + (z - 1) * S + y * S * S] = new Light { torch = light }; lightArray.c[x + z * S + (y - 1) * S * S] = new Light { torch = light }; lightArray.c[x + 1 + z * S + y * S * S] = new Light { torch = light }; lightArray.c[x + (z + 1) * S + y * S * S] = new Light { torch = light }; lightArray.c[x + z * S + (y + 1) * S * S] = new Light { torch = light }; AddBlockFaces(x, y, z, ref data, ref blockArray, ref lightArray, blockData); // to correct x,y,z offset for (int i = 0; i < vertices.Length; ++i) { vertices[i] = (vertices[i] - (Vector3.one * 0.75f)) * 2.0f; } UpdateMeshFilter(filter, vertices, normals, uvs, uv2s, colors, triangles); }
static void AddNorthFace(int x, int y, int z, ref NativeMeshData data) { Vector3 v; v.x = x + 1.0f; v.y = y; v.z = z + 1.0f; data.vertices.Add(v / Chunk.BPU); v.y = y + 1.0f; data.vertices.Add(v / Chunk.BPU); v.x = x; data.vertices.Add(v / Chunk.BPU); v.y = y; data.vertices.Add(v / Chunk.BPU); }
public static void BuildNaive(ref NativeMeshData meshData, ref NativeArray3x3 <Block> blocks, ref NativeArray3x3 <Light> lights, NativeArray <BlockData> blockData) { for (int y = 0; y < S; y++) { for (int z = 0; z < S; z++) { for (int x = 0; x < S; x++) { //blocks.c[x + z * S + y * S * S].GetType().AddDataNative(x, y, z, ref data, ref blocks, ref lights, faces); BlockData bd = blockData[blocks.c[x + z * S + y * S * S].type]; if (bd.renderType > 0) { AddBlockFaces(x, y, z, ref meshData, ref blocks, ref lights, blockData); } } } } }
// also record list of who needs to update after this (if u edit their light) public void Execute() { #if _DEBUG long initLightTime = 0; long processLightTime = 0; long meshingTime = 0; long colliderTime = 0; System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Restart(); UnityEngine.Profiling.Profiler.BeginSample("Lighting"); #endif //LightCalculator.AddSunlightRemovals(ref lights, lightOps, lightRBFS); // if chunk hasnt been rendered before then check each block to see if it has any lights if (calcInitialLight) { LightCalculator.CalcInitialLightOps(blocks.c, blockData, lightOps); #if _DEBUG initLightTime = watch.ElapsedMilliseconds; watch.Restart(); #endif LightCalculator.CalcInitialSunLight(blocks.c, blockData, lights.c, lights.u, lightBFS, upRendered, chunkWorldPos); } // always call this incase lightBFS comes with some data in it already LightCalculator.ProcessSunlight(ref lights, ref blocks, blockData, lightBFS, lightBFS_U, lightRBFS, lightRBFS_U); Assert.IsTrue(lightBFS.Count == 0 && lightRBFS.Count == 0); LightCalculator.ProcessTorchLightOpsOptimal(ref lights, ref blocks, blockData, lightOps, lightBFS, lightRBFS); Assert.IsTrue(lightBFS.Count == 0 && lightRBFS.Count == 0); int torchLightFlags = lights.flags; // add this so job controller can see after jobs done lightBFS.Enqueue(torchLightFlags); // also here maybe add nodes that weren't finished due to hitting bottom of chunks #if _DEBUG UnityEngine.Profiling.Profiler.EndSample(); processLightTime = watch.ElapsedMilliseconds; watch.Restart(); UnityEngine.Profiling.Profiler.BeginSample("Meshing"); #endif NativeMeshData meshData = new NativeMeshData(vertices, normals, uvs, uv2s, colors, triangles, faces); // add faces to this MeshBuilder.BuildNaive(ref meshData, ref blocks, ref lights, blockData); #if _DEBUG meshingTime = watch.ElapsedMilliseconds; watch.Restart(); UnityEngine.Profiling.Profiler.EndSample(); #endif #if GEN_COLLIDERS #if _DEBUG UnityEngine.Profiling.Profiler.BeginSample("Collider"); #endif if (genCollider) { MeshBuilder.BuildGreedyCollider(ref blocks, colliderVerts, colliderTris); } #if _DEBUG colliderTime = watch.ElapsedMilliseconds; UnityEngine.Profiling.Profiler.EndSample(); #endif #endif #if _DEBUG lightBFS.Enqueue((int)initLightTime); lightBFS.Enqueue((int)processLightTime); lightBFS.Enqueue((int)meshingTime); lightBFS.Enqueue((int)colliderTime); #endif }
static void AddUVs(int x, int y, int z, ref NativeMeshData data, ref NativeArray3x3 <Block> blocks, NativeArray <BlockData> blockData, Dir dir, bool isLight) { // calculate uv1s, xy is uv coordinates, z is texture type BlockData bd = blockData[blocks.Get(x, y, z).type]; if (bd.renderType == 1) // normal texture { if (bd.texture < 0) // dynamic, depends on nearby blocks { data.AddFaceUVs(GetTextureIndex(dir, x, y, z, ref blocks)); } else { data.AddFaceUVs(bd.texture); } } else if (bd.renderType == 2) // using tiling textures { if (bd.texture < 0) // dynamic, depends on nearby blocks { int texture = GetTileTextureIndex(dir, x, y, z, ref blocks); data.AddTileUvs(texture, dir, x, y, z, ref blocks, blockData); } else { data.AddTileUvs(bd.texture, dir, x, y, z, ref blocks, blockData); } } // now add uv2s, x is tiletype and y is ambient occlusion (z is unused for now) Vector3 uv2_0, uv2_1, uv2_2, uv2_3; uv2_0 = uv2_1 = uv2_2 = uv2_3 = default; uv2_0.x = uv2_1.x = uv2_2.x = uv2_3.x = bd.renderType == 1 ? 0.5f : 1.5f; if (isLight) { uv2_0.y = uv2_1.y = uv2_2.y = uv2_3.y = 1.0f; // dont add ao on the faces of lights, looks weird } else { switch (dir) { case Dir.west: { int up = GetOpacity(ref blocks, blockData, x - 1, y + 1, z); int down = GetOpacity(ref blocks, blockData, x - 1, y - 1, z); int north = GetOpacity(ref blocks, blockData, x - 1, y, z + 1); int south = GetOpacity(ref blocks, blockData, x - 1, y, z - 1); uv2_0.y = CalcAO(down, north, ref blocks, blockData, x - 1, y - 1, z + 1); uv2_1.y = CalcAO(up, north, ref blocks, blockData, x - 1, y + 1, z + 1); uv2_2.y = CalcAO(up, south, ref blocks, blockData, x - 1, y + 1, z - 1); uv2_3.y = CalcAO(down, south, ref blocks, blockData, x - 1, y - 1, z - 1); } break; case Dir.down: { int north = GetOpacity(ref blocks, blockData, x, y - 1, z + 1); int south = GetOpacity(ref blocks, blockData, x, y - 1, z - 1); int east = GetOpacity(ref blocks, blockData, x + 1, y - 1, z); int west = GetOpacity(ref blocks, blockData, x - 1, y - 1, z); uv2_0.y = CalcAO(south, west, ref blocks, blockData, x - 1, y - 1, z - 1); uv2_1.y = CalcAO(south, east, ref blocks, blockData, x + 1, y - 1, z - 1); uv2_2.y = CalcAO(north, east, ref blocks, blockData, x + 1, y - 1, z + 1); uv2_3.y = CalcAO(north, west, ref blocks, blockData, x - 1, y - 1, z + 1); } break; case Dir.south: { int up = GetOpacity(ref blocks, blockData, x, y + 1, z - 1); int down = GetOpacity(ref blocks, blockData, x, y - 1, z - 1); int east = GetOpacity(ref blocks, blockData, x + 1, y, z - 1); int west = GetOpacity(ref blocks, blockData, x - 1, y, z - 1); uv2_0.y = CalcAO(down, west, ref blocks, blockData, x - 1, y - 1, z - 1); uv2_1.y = CalcAO(up, west, ref blocks, blockData, x - 1, y + 1, z - 1); uv2_2.y = CalcAO(up, east, ref blocks, blockData, x + 1, y + 1, z - 1); uv2_3.y = CalcAO(down, east, ref blocks, blockData, x + 1, y - 1, z - 1); } break; case Dir.east: { int up = GetOpacity(ref blocks, blockData, x + 1, y + 1, z); int down = GetOpacity(ref blocks, blockData, x + 1, y - 1, z); int north = GetOpacity(ref blocks, blockData, x + 1, y, z + 1); int south = GetOpacity(ref blocks, blockData, x + 1, y, z - 1); uv2_0.y = CalcAO(down, south, ref blocks, blockData, x + 1, y - 1, z - 1); uv2_1.y = CalcAO(up, south, ref blocks, blockData, x + 1, y + 1, z - 1); uv2_2.y = CalcAO(up, north, ref blocks, blockData, x + 1, y + 1, z + 1); uv2_3.y = CalcAO(down, north, ref blocks, blockData, x + 1, y - 1, z + 1); } break; case Dir.up: { int north = GetOpacity(ref blocks, blockData, x, y + 1, z + 1); int south = GetOpacity(ref blocks, blockData, x, y + 1, z - 1); int east = GetOpacity(ref blocks, blockData, x + 1, y + 1, z); int west = GetOpacity(ref blocks, blockData, x - 1, y + 1, z); uv2_0.y = CalcAO(north, west, ref blocks, blockData, x - 1, y + 1, z + 1); uv2_1.y = CalcAO(north, east, ref blocks, blockData, x + 1, y + 1, z + 1); uv2_2.y = CalcAO(south, east, ref blocks, blockData, x + 1, y + 1, z - 1); uv2_3.y = CalcAO(south, west, ref blocks, blockData, x - 1, y + 1, z - 1); } break; case Dir.north: { int up = GetOpacity(ref blocks, blockData, x, y + 1, z + 1); int down = GetOpacity(ref blocks, blockData, x, y - 1, z + 1); int east = GetOpacity(ref blocks, blockData, x + 1, y, z + 1); int west = GetOpacity(ref blocks, blockData, x - 1, y, z + 1); uv2_0.y = CalcAO(down, east, ref blocks, blockData, x + 1, y - 1, z + 1); uv2_1.y = CalcAO(up, east, ref blocks, blockData, x + 1, y + 1, z + 1); uv2_2.y = CalcAO(up, west, ref blocks, blockData, x - 1, y + 1, z + 1); uv2_3.y = CalcAO(down, west, ref blocks, blockData, x - 1, y - 1, z + 1); } break; default: break; } } data.uv2s.Add(uv2_0); data.uv2s.Add(uv2_1); data.uv2s.Add(uv2_2); data.uv2s.Add(uv2_3); // do anisotropy flip if (uv2_0.y + uv2_2.y > uv2_1.y + uv2_3.y) { data.AddQuadTriangles(); } else { data.AddFlippedQuadTriangles(); } }
static void AddBlockFaces(int x, int y, int z, ref NativeMeshData data, ref NativeArray3x3 <Block> blocks, ref NativeArray3x3 <Light> lights, NativeArray <BlockData> blockData) { bool isLight = LightCalculator.GetIsLight(lights.Get(x, y, z).torch); if (!BlockData.RenderSolid(blockData, blocks.Get(x - 1, y, z), Dir.east)) { AddWestFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.west, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x - 1, y, z))); data.AddFaceNormal(Dirs.norm3f[Dirs.WEST]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.west }); } if (!BlockData.RenderSolid(blockData, blocks.Get(x, y - 1, z), Dir.up)) { AddDownFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.down, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y - 1, z))); data.AddFaceNormal(Dirs.norm3f[Dirs.DOWN]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.down }); } if (!BlockData.RenderSolid(blockData, blocks.Get(x, y, z - 1), Dir.north)) { AddSouthFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.south, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y, z - 1))); data.AddFaceNormal(Dirs.norm3f[Dirs.SOUTH]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.south }); } if (!BlockData.RenderSolid(blockData, blocks.Get(x + 1, y, z), Dir.west)) { AddEastFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.east, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x + 1, y, z))); data.AddFaceNormal(Dirs.norm3f[Dirs.EAST]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.east }); } if (!BlockData.RenderSolid(blockData, blocks.Get(x, y + 1, z), Dir.down)) { AddUpFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.up, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y + 1, z))); data.AddFaceNormal(Dirs.norm3f[Dirs.UP]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.up }); } if (!BlockData.RenderSolid(blockData, blocks.Get(x, y, z + 1), Dir.south)) { AddNorthFace(x, y, z, ref data); AddUVs(x, y, z, ref data, ref blocks, blockData, Dir.north, isLight); data.AddFaceColor(LightCalculator.GetColorFromLight(lights.Get(x, y, z + 1))); data.AddFaceNormal(Dirs.norm3f[Dirs.NORTH]); data.faces.Add(new Face { pos = (ushort)(x + z * Chunk.SIZE + y * Chunk.SIZE * Chunk.SIZE), dir = Dir.north }); } }