public RuntimeSurfaceGeometryModule_Side( LevelEntity_Side sideEntity, LevelEntity_Side.DataSources dataSource, Mesh surfaceMesh, MeshRenderer surfaceRenderer) : base() { this.sideEntity = sideEntity; this.dataSource = dataSource; SurfaceMesh = surfaceMesh; SurfaceRenderer = surfaceRenderer; }
private static void CreateSideRoot(ref LevelEntity_Side runtimeSide, bool isClockwise, short sideIndex, Side side, LevelEntity_Level parentLevel, short parentLineIndex) { if (!runtimeSide) { var sideGO = new GameObject(isClockwise ? $"Clockwise ({sideIndex})" : $"Counterclockwise ({sideIndex})"); runtimeSide = sideGO.AddComponent <LevelEntity_Side>(); runtimeSide.ParentLineIndex = parentLineIndex; runtimeSide.IsClockwise = isClockwise; runtimeSide.InitializeEntity(parentLevel, sideIndex, side); parentLevel.Sides[sideIndex] = runtimeSide; } }
public void GenerateSurfaces() { ClockwiseSide = LevelEntity_Side.AssembleEntity(ParentLevel, isClockwise: true, NativeIndex); if (ClockwiseSide) { ClockwiseSide.transform.SetParent(transform); } CounterclockwiseSide = LevelEntity_Side.AssembleEntity(ParentLevel, isClockwise: false, NativeIndex); if (CounterclockwiseSide) { CounterclockwiseSide.transform.SetParent(transform); } }
public virtual void InitializeRuntimeSurface( LevelEntity_Side entity, LevelEntity_Side.DataSources dataSource) { if (geometryModule != null) { throw new Exception("Cannot initialize surface more than once."); } var mesh = new Mesh(); gameObject.AddComponent <MeshFilter>().sharedMesh = mesh; geometryModule = new RuntimeSurfaceGeometryModule_Side( entity, dataSource, mesh, gameObject.AddComponent <MeshRenderer>()); AssembleSurface(); }
public static LevelEntity_Side AssembleEntity(LevelEntity_Level level, bool isClockwise, short lineIndex) { var line = level.Level.Lines[lineIndex]; var sideIndex = isClockwise ? line.ClockwisePolygonSideIndex : line.CounterclockwisePolygonSideIndex; // Note: A null-side may still be created as an untextured side var side = sideIndex < level.Level.Sides.Count && sideIndex >= 0 ? level.Level.Sides[sideIndex] : null; #region Facing_Elevations var facingPolygonIndex = isClockwise ? line.ClockwisePolygonOwner : line.CounterclockwisePolygonOwner; if (facingPolygonIndex < 0) { return(null); } var facingPolygon = level.Level.Polygons[facingPolygonIndex]; Platform facingPlatform; facingPlatform = GeometryUtilities.GetPlatformForPolygon(level.Level, facingPolygon); var highestFacingCeiling = facingPolygon.CeilingHeight; var lowestFacingFloor = facingPolygon.FloorHeight; if (facingPlatform != null) { if (facingPlatform.ComesFromFloor && facingPlatform.ComesFromCeiling) { var roundedMidpoint = (short)Mathf.RoundToInt((facingPlatform.RuntimeMinimumHeight(level.Level) + facingPlatform.RuntimeMaximumHeight(level.Level)) * 0.5f); highestFacingCeiling = (short)Mathf.Max(highestFacingCeiling, roundedMidpoint); lowestFacingFloor = (short)Mathf.Min(lowestFacingFloor, roundedMidpoint); } else if (facingPlatform.ComesFromFloor) { lowestFacingFloor = (short)Mathf.Min(lowestFacingFloor, facingPlatform.RuntimeMinimumHeight(level.Level)); } else if (facingPlatform.ComesFromCeiling) { highestFacingCeiling = (short)Mathf.Max(highestFacingCeiling, facingPlatform.RuntimeMaximumHeight(level.Level)); } } #endregion Facing_Elevations #region Opposing_Elevations var opposingPolygonIndex = isClockwise ? line.CounterclockwisePolygonOwner : line.ClockwisePolygonOwner; var hasOpposingPolygon = opposingPolygonIndex >= 0; var opposingPolygon = hasOpposingPolygon ? level.Level.Polygons[opposingPolygonIndex] : null; Platform opposingPlatform = null; if (opposingPolygon != null) { opposingPlatform = GeometryUtilities.GetPlatformForPolygon(level.Level, opposingPolygon); } var lowestOpposingCeiling = hasOpposingPolygon ? opposingPolygon.CeilingHeight : highestFacingCeiling; var highestOpposingCeiling = lowestOpposingCeiling; var highestOpposingFloor = hasOpposingPolygon ? opposingPolygon.FloorHeight : lowestFacingFloor; var lowestOpposingFloor = highestOpposingFloor; if (opposingPlatform != null) { if (opposingPlatform.ComesFromFloor && opposingPlatform.ComesFromCeiling) { var roundedMidpoint = (short)Mathf.RoundToInt((opposingPlatform.RuntimeMinimumHeight(level.Level) + opposingPlatform.RuntimeMaximumHeight(level.Level)) * 0.5f); highestOpposingFloor = (short)Mathf.Max(highestOpposingFloor, roundedMidpoint); lowestOpposingCeiling = (short)Mathf.Min(lowestOpposingCeiling, roundedMidpoint); } else if (opposingPlatform.ComesFromFloor) { highestOpposingFloor = (short)Mathf.Max(highestOpposingFloor, opposingPlatform.RuntimeMaximumHeight(level.Level)); lowestOpposingFloor = opposingPlatform.RuntimeMinimumHeight(level.Level); } else if (opposingPlatform.ComesFromCeiling) { highestOpposingCeiling = opposingPlatform.RuntimeMaximumHeight(level.Level); lowestOpposingCeiling = (short)Mathf.Min(lowestOpposingCeiling, opposingPlatform.RuntimeMinimumHeight(level.Level)); } } #endregion Opposing_Elevations #region Exposure_Determination // Data-driven surface-exposure var dataExpectsFullSide = side != null && side.Type == SideType.Full && !side.Primary.Texture.IsEmpty(); var dataExpectsTop = !dataExpectsFullSide && side != null && (side.Type == SideType.High || side.Type == SideType.Split); // Geometry-driven surface-exposure var exposesTop = !dataExpectsFullSide && hasOpposingPolygon && highestFacingCeiling > lowestOpposingCeiling; var exposesMiddle = (!hasOpposingPolygon || (line.Flags & LineFlags.HasTransparentSide) != 0 || dataExpectsFullSide) && highestFacingCeiling > lowestFacingFloor && (highestOpposingCeiling > lowestOpposingFloor || dataExpectsFullSide); var exposesBottom = !dataExpectsFullSide && hasOpposingPolygon && highestOpposingFloor > lowestFacingFloor; #endregion Exposure_Determination #region Surface_Assembly LevelEntity_Side runtimeSide = null; if (exposesTop) { // Top is always Primary var sideDataSource = DataSources.Primary; var highHeight = highestFacingCeiling; var lowHeight = lowestOpposingCeiling; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; var surface = new GameObject($"Side Top ({sideIndex}) (High - Source:{sideDataSource})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); runtimeSide.PrimarySurface = surface; runtimeSide.TopSurface = surface; } if (exposesMiddle) { // Primary if there's no opposing polygon or it's explicitly "full", Transparent otherwise var sideDataSource = (!hasOpposingPolygon || dataExpectsFullSide) ? DataSources.Primary : DataSources.Transparent; var hasLayeredTransparentSide = side.HasLayeredTransparentSide(level.Level); var highHeight = dataExpectsFullSide ? highestFacingCeiling : line.LowestAdjacentCeiling; var lowHeight = dataExpectsFullSide ? lowestFacingFloor : line.HighestAdjacentFloor; var typeDescriptor = hasOpposingPolygon ? $"Transparent - HasTransparentSide - Source:{sideDataSource}" : $"Full - Unopposed - Source:{sideDataSource}"; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; } if (sideDataSource == DataSources.Transparent || hasLayeredTransparentSide) { runtimeSide.TransparentHighElevation = highHeight; runtimeSide.TransparentLowElevation = lowHeight; } var surface = new GameObject($"Side Middle ({sideIndex}) - ({typeDescriptor})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimarySurface = surface; } if (sideDataSource == DataSources.Transparent || hasLayeredTransparentSide) { runtimeSide.TransparentSurface = surface; } runtimeSide.MiddleSurface = surface; } if (exposesBottom) { // Secondary if there is an exposable or expected (in data) top section var sideDataSource = dataExpectsTop ? DataSources.Secondary : DataSources.Primary; var highHeight = highestOpposingFloor; var lowHeight = lowestFacingFloor; CreateSideRoot(ref runtimeSide, isClockwise, sideIndex, side, level, lineIndex); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimaryHighElevation = highHeight; runtimeSide.PrimaryLowElevation = lowHeight; } else { runtimeSide.SecondaryHighElevation = highHeight; runtimeSide.SecondaryLowElevation = lowHeight; } var surface = new GameObject($"Side Bottom ({sideIndex}) (Low - Source:{sideDataSource})").AddComponent <RuntimeSurfaceGeometry>(); surface.transform.SetParent(runtimeSide.transform); surface.InitializeRuntimeSurface(runtimeSide, sideDataSource); if (sideDataSource == DataSources.Primary) { runtimeSide.PrimarySurface = surface; } else { runtimeSide.SecondarySurface = surface; } runtimeSide.BottomSurface = surface; } #endregion Surface_Assembly return(runtimeSide); }