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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }