public Bounds AlignBounds(TreeImportSettings settings, Bounds bounds) { var origin = bounds.min.y; var step = EditorTreeUtility.GetStepAtTreeLevel(bounds, settings, settings.meshDetailLevel); var alignedBounds = TreeUtility.GetRoundedAlignedBounds(bounds, bounds.min, step); var alignedOrigin = alignedBounds.min.y; var peak = FindPeak(); var targetCenter = origin + (bounds.size.y / Resolution) * (peak + 0.5f); var tmpDst = float.MaxValue; var actualCenter = 0f; for (var i = 0; i < (int)(alignedBounds.size.y / step); ++i) { var pos = alignedOrigin + (i + 0.5f) * step; var dst = Mathf.Abs(targetCenter - pos); if (dst < tmpDst) { actualCenter = pos; tmpDst = dst; } else { Debug.Log($"Break at i ({actualCenter:F4})"); break; } } var diff = targetCenter - actualCenter; if (diff > 0) { diff -= step; } var height = bounds.max.y - bounds.min.y; var alignedMin = alignedBounds.min; alignedMin.y += diff; alignedBounds.min = alignedMin; Debug.Log($"origin: {origin:F4}, AO: {alignedBounds.min.y:F4}, height: {height:F4}, step: {step:F4}, TC: {targetCenter:F4}, AC: {actualCenter:F4}"); return(alignedBounds); }
public void UpdateForNode(NodeRecord record, float minimumDistance, bool alignDistance = false) { nodeRecord = record; if (alignDistance) { var newDist = Mathf.Min(rootBounds.size.x, rootBounds.size.z) / settings.rootNodeSubdivision; while (0.5f * newDist > settings.minPointDistance) { newDist *= 0.5f; } minimumDistance = newDist; } cellStep = minimumDistance; alignedBounds = TreeUtility.GetRoundedAlignedBounds(nodeRecord.Bounds, rootBounds.min, minimumDistance); EditorTreeUtility.CalculateGridSize(alignedBounds, minimumDistance, cellsPerAxis); }
protected override void DoWorkInternal(NodeRecord record) { var mainFilePath = Path.Combine(tmpDataPath, $"{record.Identifier}.meshdata"); EditorTreeUtility.LoadMeshGenerationData(mainFilePath, voxelData); var intermediateMesh = new MeshData(); for (var i = 1; i < LutOffsets.Length; ++i) { if (TryGetNeighbourId(record.Identifier, LutOffsets[i], out var neighbourId)) { var edgePath = Path.Combine(tmpDataPath, $"{neighbourId}.meshedge"); if (!File.Exists(edgePath)) { neighborData[LutOffsets[i]].Clear(); continue; } EditorTreeUtility.LoadMeshGenerationData(edgePath, neighborData[LutOffsets[i]]); } else { neighborData[LutOffsets[i]].Clear(); } } for (var i = 0; i < settings.erosionPasses; ++i) { ProcessErode(record); } var step = Mathf.Min(record.Bounds.size.x, record.Bounds.size.z) / settings.rootNodeSubdivision; var alignedBounds = TreeUtility.GetRoundedAlignedBounds(record.Bounds, importData.Bounds.min, step); var roadBounds = importData.RoadBounds; var centerOffset = Vector3.one * (step * 0.5f); for (var x = 0; x < voxelData.gridSize[0]; x++) { for (var y = 0; y < voxelData.gridSize[1]; y++) { for (var z = 0; z < voxelData.gridSize[2]; z++) { if (cancelFlag) { return; } var coord = new Vector3Int(x, y, z); for (var i = 0; i < LutOffsets.Length; i++) { var pos = coord + LutOffsets[i]; if (!TryGetBuilderVert(pos, out var vert)) { cube[i] = null; } else if (!roadBounds.Contains(vert.position)) { cube[i] = null; } else { var rel = vert.position - alignedBounds.min; var value = rel - (Vector3)pos * step - centerOffset; cube[i] = value; } } ProcessCube(coord, intermediateMesh); VoxelsDone++; } } } for (var i = 0; i < settings.erosionPasses; ++i) { LevelPoints(); } var finalMesh = ProcessFinalMesh(intermediateMesh); var filePath = Path.Combine(dataPath, record.Identifier + TreeUtility.MeshFileExtension); finalMesh.SaveToFile(filePath); }