private void AddWallInfo(int i, int j) { for (int k = 0; k < vertsInStack.Count; k++) { VertInStack vis = vertsInStack[k]; CellVertInfo cvi = cellVertInfos[(vis.coords.y - cyMin) * cw + (vis.coords.x - cxMin)]; if (vis.cell.state == MapCell.State.Full) { for (int l = 0; l < vertsInStack.Count; l++) { VertInStack vis2 = vertsInStack[l]; if (vis2.cell.state == MapCell.State.Excavated) { HexXY diff = vis2.coords - vis.coords; int neighIdx = HexXY.DiffToNeighIndex(diff.x, diff.y); cvi.WallVertices[neighIdx].High.Add(vis.mesh.vertices[vis.vidx]); cvi.WallVertices[neighIdx].Low.Add(vis2.mesh.vertices[vis2.vidx]); cvi.WallVertices[neighIdx].GridCoords.Add(new Vector2Int(i, j)); cvi.WallCount++; } } } } }
public HexMeshGenerator(int patchSize, int subDivsShift) { Debug.Assert((patchSize % 3) == 0); this.patchSize = patchSize; this.subDivsShift = subDivsShift; this.subDivs = 1 << subDivsShift; this.subDivsMask = subDivs - 1; this.cxMin = 0; this.cyMin = -patchSize / 3; this.cw = patchSize + 1; this.ch = 2 * patchSize / 3 + 1; this.subdivRhex = rhex / subDivs; this.subdivRhey = rhey / subDivs; this.cellVertInfos = new CellVertInfo[cw * ch]; for (int i = 0; i < ch; i++) { for (int j = 0; j < cw; j++) { CellVertInfo cvi = new CellVertInfo(new HexXY(cxMin + j, cyMin + i)); this.cellVertInfos[i * cw + j] = cvi; } } this.vertsInStack = new List <VertInStack>(3); noise = new PerlinNoise(); }
private void AddNearCellVertices(int row, int col, HexXY cellCoords, MapCell cell) { MeshData mesh = selectCellMesh(cell); int sharedIdx = -1; for (int l = 0; l < vertsInStack.Count; l++) { if (vertsInStack[l].mesh == mesh) { sharedIdx = vertsInStack[l].vidx; break; } } int idx; if (sharedIdx == -1) { Vector2 patchOffset = patchOffsetX * patchSize * rhex + patchOffsetY * patchSize * rhey; idx = mesh.vertices.Count; Vector2 planeCoords = row * subdivRhey + col * subdivRhex; float y = cell.state == MapCell.State.Full ? 1 : 0; Vector3 vertex = new Vector3(planeCoords.x, y, planeCoords.y); //TODO: move noise out float noiseStrength = 0.1f; PerlinNoiseSample vNoise = noise.Perlin2D(patchOffset + planeCoords, 0.5f); vertex.y += vNoise.value * noiseStrength; mesh.vertices.Add(vertex); Vector2 uvPos = patchOffset + new Vector2(planeCoords.x, planeCoords.y); mesh.uvs.Add(uvPos); Vector3 normal = new Vector3(-vNoise.derivative.x * noiseStrength, 1, -vNoise.derivative.y * noiseStrength).normalized; mesh.normals.Add(normal); } else { idx = sharedIdx; } vertsInStack.Add(new VertInStack() { cell = cell, mesh = mesh, vidx = idx, coords = cellCoords }); CellVertInfo cvi = cellVertInfos[(cellCoords.y - cyMin) * cw + (cellCoords.x - cxMin)]; cvi.SetMesh(mesh); cvi.AddIdx(row, idx); }
public void GenerateWalls(MeshData wallMesh) { int nextIdx = 0; int cw = patchSize + 1; int ch = 2 * patchSize / 3 + 1; for (int i = 0; i < ch; i++) { for (int j = 0; j < cw; j++) { CellVertInfo cvi = cellVertInfos[i * cw + j]; if (cvi.WallCount > 1) { for (int k = 0; k < 6; k++) { WallVerticesInfo wis = cvi.WallVertices[k]; if (wis.High.Count < 2) { continue; } for (int l = 0; l < wis.High.Count; l++) { //Verts Vector3 highVert = wis.High[l]; Vector3 lowVert = wis.Low[l]; wallMesh.vertices.Add(highVert); wallMesh.vertices.Add(lowVert); //UVs Vector2Int gridCoords = wis.GridCoords[l]; gridCoords.x += patchOffsetX * patchSize * subDivs; gridCoords.y += patchOffsetY * patchSize * subDivs; float u = WallUForGridCoords(gridCoords); wallMesh.uvs.Add(new Vector2(u, 1)); wallMesh.uvs.Add(new Vector2(u, 0)); //Normals //TODO: just neigbours for now, can smooth later if needed Vector3 highNeigh; if (l == 0) { highNeigh = wis.High[l + 1]; } else { highNeigh = wis.High[l - 1]; } Vector3 normal = Vector3.Cross(highNeigh - highVert, lowVert - highVert); if (l > 0) { normal = -normal; } if (!(k >= 1 && k <= 3)) { normal = -normal; } normal = normal.normalized; wallMesh.normals.Add(normal); wallMesh.normals.Add(normal); } for (int l = 0; l < wis.High.Count - 1; l++) { //Cut 0,0 outermost walls (duplicate walls in different patches cause z-fighting Vector2Int gridCoords0 = wis.GridCoords[l]; Vector2Int gridCoords1 = wis.GridCoords[l + 1]; if ((gridCoords0.x == 0 && gridCoords1.x == 0) || (gridCoords0.y == 0 && gridCoords1.y == 0)) { nextIdx += 2; continue; } //Different winding order due to wall vertices //filling order in main mesh generation above if (k >= 1 && k <= 3) { wallMesh.triangles.Add(nextIdx); wallMesh.triangles.Add(nextIdx + 3); wallMesh.triangles.Add(nextIdx + 1); wallMesh.triangles.Add(nextIdx); wallMesh.triangles.Add(nextIdx + 2); wallMesh.triangles.Add(nextIdx + 3); } else { wallMesh.triangles.Add(nextIdx); wallMesh.triangles.Add(nextIdx + 1); wallMesh.triangles.Add(nextIdx + 3); wallMesh.triangles.Add(nextIdx); wallMesh.triangles.Add(nextIdx + 3); wallMesh.triangles.Add(nextIdx + 2); } nextIdx += 2; } nextIdx = wallMesh.vertices.Count; } } } } }
private void FillTriangleIndices(CellVertInfo cvi) { MeshData mesh = cvi.Mesh; for (int r = 0; r < cvi.RowStarts.Count - 1; r++) { int rowStart = cvi.RowStarts[r]; int nextRowStart = cvi.RowStarts[r + 1]; int afterNextRowStart = r == cvi.RowStarts.Count - 2 ? cvi.Idxs.Count : cvi.RowStarts[r + 2]; int rowLen = nextRowStart - rowStart; int nextRowLen = afterNextRowStart - nextRowStart; //TODO: simplify cases? if (rowLen == nextRowLen) //this rhombus part always leans to the right { for (int k = 0; k < rowLen - 1; k++) { mesh.triangles.Add(cvi.Idxs[rowStart + k]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k]); mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k + 1]); } } else if (rowLen < nextRowLen) { mesh.triangles.Add(cvi.Idxs[rowStart]); mesh.triangles.Add(cvi.Idxs[nextRowStart]); mesh.triangles.Add(cvi.Idxs[nextRowStart + 1]); for (int k = 0; k < rowLen - 1; k++) { mesh.triangles.Add(cvi.Idxs[rowStart + k]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k + 2]); } } else { for (int k = 0; k < rowLen - 1; k++) { mesh.triangles.Add(cvi.Idxs[rowStart + k]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k]); mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); if (k < rowLen - 2) { mesh.triangles.Add(cvi.Idxs[rowStart + k + 1]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k]); mesh.triangles.Add(cvi.Idxs[nextRowStart + k + 1]); } } } } }