/// <summary> /// Given a set of points ordered counter-clockwise along a contour and a set of holes, return triangle indexes. /// </summary> /// <param name="points"></param> /// <param name="holes"></param> /// <param name="indexes">Indices outside of the points list index into holes when layed out linearly. /// {vertices 0,1,2...vertices.length-1, holes 0 values, hole 1 values etc.} </param> /// <returns></returns> public static bool Triangulate(IList <Vector2> points, IList <IList <Vector2> > holes, out List <int> indexes) { indexes = new List <int>(); int index = 0; var allPoints = new List <Vector2>(points); Polygon polygon = new Polygon(points.Select(x => new PolygonPoint(x.x, x.y, index++))); if (holes != null) { for (int i = 0; i < holes.Count; i++) { allPoints.AddRange(holes[i]); var holePolgyon = new Polygon(holes[i].Select(x => new PolygonPoint(x.x, x.y, index++))); polygon.AddHole(holePolgyon); } } try { P2T.Triangulate(TriangulationAlgorithm.DTSweep, polygon); } catch (System.Exception e) { Log.Info("Triangulation failed: " + e.ToString()); return(false); } foreach (DelaunayTriangle d in polygon.Triangles) { if (d.Points[0].Index < 0 || d.Points[1].Index < 0 || d.Points[2].Index < 0) { Log.Info("Triangulation failed: Additional vertices were inserted."); return(false); } indexes.Add(d.Points[0].Index); indexes.Add(d.Points[1].Index); indexes.Add(d.Points[2].Index); } WindingOrder originalWinding = SurfaceTopology.GetWindingOrder(points); // if the re-triangulated first tri doesn't match the winding order of the original // vertices, flip 'em if (SurfaceTopology.GetWindingOrder(new Vector2[3] { allPoints[indexes[0]], allPoints[indexes[1]], allPoints[indexes[2]], }) != originalWinding) { indexes.Reverse(); } return(true); }
// Return the modular distance from one angle to another using the given winding order. public static int GetAngleDistance(int startAngle, int endAngle, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { if (endAngle > startAngle) { return(startAngle + Angles.AngleCount - endAngle); } else { return(startAngle - endAngle); } } else { if (endAngle < startAngle) { return(endAngle + Angles.AngleCount - startAngle); } else { return(endAngle - startAngle); } } }
// Ensures that a set of vertices are wound in the desired winding order public void EnsureWindingOrder(WindingOrder windingOrder) { if (!DetermineWindingOrder().Equals(windingOrder)) { ReverseWindingOrder(); } }
public override Vertices GenerateAroundCentroid(Vector2 centroid, float vertexAlignmentRay = 0, bool alignAroundRay = true, WindingOrder windingOrder = WindingOrder.CounterClockwise) { var vertices = GenerateFromInitial(Vector2.Zero, 0, windingOrder); var transformedVertices = new List <Vector2>(NumVertices); var currentCentroid = new Vector2(); currentCentroid = vertices.Aggregate(currentCentroid, (current, tempVertex) => (Vector2)(current + tempVertex)); currentCentroid *= 1f / NumVertices; for (int i = 0; i < NumVertices; i++) { transformedVertices.Add((Vector2)vertices[i]); transformedVertices[i] -= currentCentroid; } float alignmentAngle = vertexAlignmentRay - (alignAroundRay ? (transformedVertices[0].Direction + transformedVertices[1].Direction) / 2 : transformedVertices[0].Direction); vertices = new Vertices(transformedVertices); var transform = new Transform(); transform.Rotate(alignmentAngle); transform.Translate(centroid); return(transform.ApplyTransform(vertices)); }
//----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- public PlayerSpinSwordState() { limitTilesToDirection = false; isReswingable = false; lunge = false; swingAnglePullBack = 0; swingAngleDurations = new int[] { 3, 2, 3, 2, 3, 2, 3, 2, 5 }; weaponSwingAnimation = GameData.ANIM_SWORD_SPIN; playerSwingAnimation = GameData.ANIM_PLAYER_SPIN; // Will always spin clockwise. swingWindingOrders = new WindingOrder[] { WindingOrder.Clockwise, WindingOrder.Clockwise, WindingOrder.Clockwise, WindingOrder.Clockwise }; swingCollisionBoxesNoLunge = new Rectangle2I[4, 9]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 9; j++) { int angle = GMath.Wrap((i * 2) - j, Angles.AngleCount); swingCollisionBoxesNoLunge[i, j] = SWING_TOOL_BOXES_SPIN[angle]; } } }
//----------------------------------------------------------------------------- // Methods //----------------------------------------------------------------------------- public static int Add(int direction, int addAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) direction -= addAmount; else direction += addAmount; return GMath.Wrap(direction, Directions.Count); }
//----------------------------------------------------------------------------- // Methods //----------------------------------------------------------------------------- public static int Add(int angle, int addAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) angle -= addAmount; else angle += addAmount; return GMath.Wrap(angle, Angles.AngleCount); }
/// <summary> /// Ensures that a set of vertices are wound in a particular order, reversing them if necessary. /// </summary> /// <param name="vertices">The vertices of the polygon.</param> /// <param name="windingOrder">The desired winding order.</param> /// <returns>A new set of vertices if the winding order didn't match; otherwise the original set.</returns> public static Vector2[] EnsureWindingOrder(Vector2[] vertices, WindingOrder windingOrder) { if (DetermineWindingOrder(vertices) != windingOrder) { return(ReverseWindingOrder(vertices)); } return(vertices); }
public MaskedMeshParamters(UnityHeightMap heightMap, UnityHeightMap maskMap, float maskThreshold, int meshResolution, Vector3 meshScale, int meshType, WindingOrder winding) { Heightmap = heightMap; Maskmap = maskMap; MaskThreshold = maskThreshold; MeshResolution = meshResolution; MeshScale = meshScale; MeshType = meshType; Winding = winding; }
//----------------------------------------------------------------------------- // Methods //----------------------------------------------------------------------------- public static int Add(int direction, int addAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { direction -= addAmount; } else { direction += addAmount; } return(GMath.Wrap(direction, Directions.Count)); }
public VoxelizationInput() { m_voxelLevel = 6; m_minVolume = 0.65f; m_minOcclusion = 0.03f; m_type = OcclusionType.BoxExpansion; m_retriangulate = true; m_removeTop = false; m_removeBottom = false; m_upAxis = UpAxis.Y; m_windingOrder = WindingOrder.CounterClockwise; }
//----------------------------------------------------------------------------- // Methods //----------------------------------------------------------------------------- public static int Add(int angle, int addAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { angle -= addAmount; } else { angle += addAmount; } return(GMath.Wrap(angle, Angles.AngleCount)); }
public static int Subtract(int angle, int subtractAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { angle += subtractAmount; } else { angle -= subtractAmount; } return(GMath.Wrap(angle, Angles.AngleCount)); }
/// <summary> /// Ensures that a set of vertices are wound in a particular order, reversing them if necessary. /// </summary> /// <param name="vertices">The vertices of the polygon.</param> /// <param name="windingOrder">The desired winding order.</param> /// <returns>A new set of vertices if the winding order didn't match; otherwise the original set.</returns> public static Vector2[] EnsureWindingOrder(Vector2[] vertices, WindingOrder windingOrder) { Log("Ensuring winding order of {0}...", windingOrder); if (DetermineWindingOrder(vertices) != windingOrder) { Log("Reversing vertices..."); return(ReverseWindingOrder(vertices)); } Log("No reversal needed."); return(vertices); }
/// <summary> /// Given a set of points ordered counter-clockwise along a contour, return triangle indexes. /// </summary> /// <param name="points"></param> /// <param name="indexes"></param> /// <param name="convex">Triangulation may optionally be set to convex, which will result in some a convex shape.</param> /// <returns></returns> public static bool Triangulate(IList <Vector2> points, out List <int> indexes, bool convex = false) { indexes = new List <int>(); int index = 0; Triangulatable soup = convex ? new PointSet(points.Select(x => new TriangulationPoint(x.x, x.y, index++)).ToList()) : (Triangulatable) new Polygon(points.Select(x => new PolygonPoint(x.x, x.y, index++))); try { triangulationContext.Clear(); triangulationContext.PrepareTriangulation(soup); DTSweep.Triangulate((DTSweepContext)triangulationContext); } catch (System.Exception e) { Log.Info("Triangulation failed: " + e.ToString()); return(false); } foreach (DelaunayTriangle d in soup.Triangles) { if (d.Points[0].Index < 0 || d.Points[1].Index < 0 || d.Points[2].Index < 0) { Log.Info("Triangulation failed: Additional vertices were inserted."); return(false); } indexes.Add(d.Points[0].Index); indexes.Add(d.Points[1].Index); indexes.Add(d.Points[2].Index); } WindingOrder originalWinding = SurfaceTopology.GetWindingOrder(points); // if the re-triangulated first tri doesn't match the winding order of the original // vertices, flip 'em if (SurfaceTopology.GetWindingOrder(new Vector2[3] { points[indexes[0]], points[indexes[1]], points[indexes[2]], }) != originalWinding) { indexes.Reverse(); } return(true); }
private void Swing(int direction) { swingDirection = direction; swingAngleDirection = swingWindingOrders[swingDirection]; swingAngleStart = Directions.ToAngle(swingDirection); swingAngleStart = Angles.Subtract(swingAngleStart, swingAnglePullBack, swingAngleDirection); swingAngle = swingAngleStart; swingAngleIndex = 0; player.Direction = direction; playerTool = GetSwingTool(); player.EquipTool(playerTool); playerTool.AnimationPlayer.SubStripIndex = direction; if (player.IsInMinecart) { playerTool.PlayAnimation(weaponSwingAnimation); player.Graphics.PlayAnimation(playerSwingAnimationInMinecart); swingCollisionBoxes = swingCollisionBoxesNoLunge; } else if (lunge) { playerTool.PlayAnimation(weaponSwingAnimationLunge); player.Graphics.PlayAnimation(playerSwingAnimationLunge); swingCollisionBoxes = swingCollisionBoxesLunge; } else { playerTool.PlayAnimation(weaponSwingAnimation); player.Graphics.PlayAnimation(playerSwingAnimation); swingCollisionBoxes = swingCollisionBoxesNoLunge; } OnSwingBegin(); // Perform an initial swing tile peak. Vector2F hitPoint = player.Center + (Angles.ToVector(swingAngle, false) * 13); Point2I hitTileLocation = player.RoomControl.GetTileLocation(hitPoint); OnSwingTilePeak(swingAngle, hitTileLocation); // Invoke any actions set to occur at time 0. if (timedActions.ContainsKey(0)) { timedActions[0].Invoke(); } Rectangle2I toolBox = swingCollisionBoxes[swingDirection, Math.Min(swingCollisionBoxes.Length - 1, swingAngleIndex)]; toolBox.Point += (Point2I)player.CenterOffset; playerTool.CollisionBox = toolBox; }
public static void MenuConformNormals() { pb_Editor editor = pb_Editor.instance; if (editor == null) { return; // this should be redundant, but y'know... safety first? } pb_Object[] selection = pbUtil.GetComponents <pb_Object>(Selection.transforms); pbUndo.RecordObjects(selection, "Conform " + (editor.selectedFaceCount > 0 ? "Face" : "Object") + " Normals."); foreach (pb_Object pb in selection) { pb_Face[] faces = pb.SelectedFaceCount > 0 ? pb.SelectedFaces : pb.faces; int len = faces.Length; int toggle = 0; WindingOrder[] winding = new WindingOrder[len]; // First figure out what the majority of the faces' winding order is for (int i = 0; i < len; i++) { winding[i] = pb.GetWindingOrder(faces[i]); toggle += (winding[i] == WindingOrder.Unknown ? 0: (winding[i] == WindingOrder.Clockwise ? 1 : -1)); } int flipped = 0; // if toggle >= 0 wind clockwise, else ccw for (int i = 0; i < len; i++) { if ((toggle >= 0 && winding[i] == WindingOrder.CounterClockwise) || (toggle < 0 && winding[i] == WindingOrder.Clockwise)) { faces[i].ReverseIndices(); flipped++; } } pb.ToMesh(); pb.Refresh(); pb.Optimize(); if (pb_Editor.instance != null) { pb_Editor.instance.UpdateSelection(); } pb_Editor_Utility.ShowNotification(flipped > 0 ? "Reversed " + flipped + " Faces" : "Normals Already Uniform"); } }
public static FrontFaceDirection To(WindingOrder windingOrder) { switch (windingOrder) { case WindingOrder.Clockwise: return(FrontFaceDirection.Cw); case WindingOrder.Counterclockwise: return(FrontFaceDirection.Ccw); } throw new ArgumentException("windingOrder"); }
public static void MenuConformNormals() { pb_Editor editor = pb_Editor.instance; if(editor == null) return; // this should be redundant, but y'know... safety first? pb_Object[] selection = pbUtil.GetComponents<pb_Object>(Selection.transforms); pbUndo.RecordObjects(selection, "Conform " + (editor.selectedFaceCount > 0 ? "Face" : "Object") + " Normals."); foreach(pb_Object pb in selection) { pb_Face[] faces = pb.SelectedFaceCount > 0 ? pb.SelectedFaces : pb.faces; int len = faces.Length; int toggle = 0; WindingOrder[] winding = new WindingOrder[len]; // First figure out what the majority of the faces' winding order is for(int i = 0; i < len; i++) { winding[i] = pb.GetWindingOrder( faces[i] ); toggle += (winding[i] == WindingOrder.Unknown ? 0: (winding[i] == WindingOrder.Clockwise ? 1 : -1)); } int flipped = 0; // if toggle >= 0 wind clockwise, else ccw for(int i = 0; i < len; i++) { if( (toggle >= 0 && winding[i] == WindingOrder.CounterClockwise) || (toggle < 0 && winding[i] == WindingOrder.Clockwise) ) { faces[i].ReverseIndices(); flipped++; } } pb.ToMesh(); pb.Refresh(); pb.Optimize(); if(pb_Editor.instance != null) pb_Editor.instance.UpdateSelection(); pb_Editor_Utility.ShowNotification(flipped > 0 ? "Reversed " + flipped + " Faces" : "Normals Already Uniform"); } }
public void ToggleDirection() { if (windingOrder == WindingOrder.Clockwise) { windingOrder = WindingOrder.CounterClockwise; arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_COUNTERCLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 1; Properties.Set("clockwise", false); } else { windingOrder = WindingOrder.Clockwise; arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_CLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 0; Properties.Set("clockwise", true); } }
//----------------------------------------------------------------------------- // Overridden methods //----------------------------------------------------------------------------- public override void OnInitialize() { base.OnInitialize(); // Create the turnstile collision model. // It loooks like this: (each character is a quarter-tile) // X X // X X // XX // XX // X X // X X CollisionModel = new CollisionModel(); CollisionModel.AddBox(0, 0, 8, 8); CollisionModel.AddBox(8, 8, 8, 8); CollisionModel.AddBox(40, 0, 8, 8); CollisionModel.AddBox(32, 8, 8, 8); CollisionModel.AddBox(0, 40, 8, 8); CollisionModel.AddBox(8, 32, 8, 8); CollisionModel.AddBox(40, 40, 8, 8); CollisionModel.AddBox(32, 32, 8, 8); CollisionModel.AddBox(16, 16, 16, 16); // center. SolidType = TileSolidType.Solid; IsSolid = true; turnDirection = -1; // Setup based on the winding order. windingOrder = (Properties.GetBoolean("clockwise", false) ? WindingOrder.Clockwise : WindingOrder.CounterClockwise); if (windingOrder == WindingOrder.Clockwise) { arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_CLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 0; } else { arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_COUNTERCLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 1; } turnstileAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ROTATE_CLOCKWISE); turnstileAnimationPlayer.SkipToEnd(); }
public override Vertices GenerateAroundCentroid(Vector2 centroid, float vertexAlignmentRay = 0, bool alignAroundRay = true, WindingOrder windingOrder = WindingOrder.CounterClockwise) { float e = EdgeLength / 2; return(new Vertices(new[] { // front new Vector3(-e, -e, e), new Vector3(e, -e, e), new Vector3(e, e, e), new Vector3(-e, e, e), // back new Vector3(-e, -e, -e), new Vector3(e, -e, -e), new Vector3(e, e, -e), new Vector3(-e, e, -e) })); }
public override Vertices GenerateFromInitial(Vector2 initialVertex, float initialExteriorAngle = 0, WindingOrder windingOrder = WindingOrder.CounterClockwise) { var tempSides = new List <Complex>(NumVertices); var tempVertices = new List <Complex>(NumVertices) { (Complex)initialVertex, (Complex)initialVertex + SideLengths[0] * Math.Exp(initialExteriorAngle * Math.I) }; tempSides.Add(SideLengths[0] * Math.Exp(initialExteriorAngle * Math.I)); for (int i = 1; i < NumVertices - 1; i++) { tempSides.Add(tempSides[i - 1] * Math.Exp(ExteriorAngles[i - 1] * Math.I) * SideLengths[i] / tempSides[i - 1].Magnitude); tempVertices.Add(tempVertices[i] + tempSides[i]); } if (windingOrder == WindingOrder.Clockwise) { tempVertices.Reverse(1, NumVertices - 1); } return(new Vertices((from tempVertex in tempVertices select(Vector2) tempVertex).ToList())); }
/// <summary> /// Ensures that a set of vertices are wound in a particular order, reversing them if necessary. /// </summary> /// <param name="vertices">The vertices of the polygon.</param> /// <param name="windingOrder">The desired winding order.</param> /// <returns>A new set of vertices if the winding order didn't match; otherwise the original set.</returns> public static Vector2[] EnsureWindingOrder(Vector2[] vertices, WindingOrder windingOrder) { Log("\nEnsuring winding order of {0}...", windingOrder); if (DetermineWindingOrder(vertices) != windingOrder) { Log("Reversing vertices..."); return ReverseWindingOrder(vertices); } Log("No reversal needed."); return vertices; }
public static int Subtract(int angle, int subtractAmount, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) angle += subtractAmount; else angle -= subtractAmount; return GMath.Wrap(angle, Angles.AngleCount); }
private void Swing(int direction) { swingDirection = direction; swingAngleDirection = swingWindingOrders[swingDirection]; swingAngleStart = Directions.ToAngle(swingDirection); swingAngleStart = Angles.Subtract(swingAngleStart, swingAnglePullBack, swingAngleDirection); swingAngle = swingAngleStart; swingAngleIndex = 0; player.Direction = direction; playerTool = GetSwingTool(); player.EquipTool(playerTool); playerTool.AnimationPlayer.SubStripIndex = direction; if (player.IsInMinecart) { playerTool.PlayAnimation(weaponSwingAnimation); player.Graphics.PlayAnimation(playerSwingAnimationInMinecart); swingCollisionBoxes = swingCollisionBoxesNoLunge; } else if (lunge) { playerTool.PlayAnimation(weaponSwingAnimationLunge); player.Graphics.PlayAnimation(playerSwingAnimationLunge); swingCollisionBoxes = swingCollisionBoxesLunge; } else { playerTool.PlayAnimation(weaponSwingAnimation); player.Graphics.PlayAnimation(playerSwingAnimation); swingCollisionBoxes = swingCollisionBoxesNoLunge; } OnSwingBegin(); // Perform an initial swing tile peak. Vector2F hitPoint = player.Center + (Angles.ToVector(swingAngle, false) * 13); Point2I hitTileLocation = player.RoomControl.GetTileLocation(hitPoint); OnSwingTilePeak(swingAngle, hitTileLocation); // Invoke any actions set to occur at time 0. if (timedActions.ContainsKey(0)) timedActions[0].Invoke(); Rectangle2I toolBox = swingCollisionBoxes[swingDirection, Math.Min(swingCollisionBoxes.Length - 1, swingAngleIndex)]; toolBox.Point += (Point2I) player.CenterOffset; playerTool.CollisionBox = toolBox; }
//----------------------------------------------------------------------------- // Overridden methods //----------------------------------------------------------------------------- public override void OnInitialize() { base.OnInitialize(); // Create the turnstile collision model. // It loooks like this: (each character is a quarter-tile) // X X // X X // XX // XX // X X // X X CollisionModel = new CollisionModel(); CollisionModel.AddBox( 0, 0, 8, 8); CollisionModel.AddBox( 8, 8, 8, 8); CollisionModel.AddBox(40, 0, 8, 8); CollisionModel.AddBox(32, 8, 8, 8); CollisionModel.AddBox( 0, 40, 8, 8); CollisionModel.AddBox( 8, 32, 8, 8); CollisionModel.AddBox(40, 40, 8, 8); CollisionModel.AddBox(32, 32, 8, 8); CollisionModel.AddBox(16, 16, 16, 16); // center. SolidType = TileSolidType.Solid; IsSolid = true; turnDirection = -1; // Setup based on the winding order. windingOrder = (Properties.GetBoolean("clockwise", false) ? WindingOrder.Clockwise : WindingOrder.CounterClockwise); if (windingOrder == WindingOrder.Clockwise) { arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_CLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 0; } else { arrowsAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ARROWS_COUNTERCLOCKWISE); turnstileAnimationPlayer.SubStripIndex = 1; } turnstileAnimationPlayer.Play(GameData.ANIM_TURNSTILE_ROTATE_CLOCKWISE); turnstileAnimationPlayer.SkipToEnd(); }
public abstract Vertices GenerateAroundCentroid(Vector2 centroid, float vertexAlignmentRay = 0, bool alignAroundRay = true, WindingOrder windingOrder = WindingOrder.CounterClockwise);
public abstract Vertices GenerateFromInitial(Vector2 initialVertex, float initialExteriorAngle = 0, WindingOrder windingOrder = WindingOrder.CounterClockwise);
// Return the modular distance from one angle to another using the given winding order. public static float GetAngleDistance(float startAngle, float endAngle, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { if (endAngle > startAngle) return (startAngle + GMath.FullAngle - endAngle); else return (startAngle - endAngle); } else { if (endAngle < startAngle) return (endAngle + GMath.FullAngle - startAngle); else return (endAngle - startAngle); } }
/// <summary> /// Triangulates a 2D polygon produced the indexes required to render the points as a triangle list. /// </summary> /// <param name="inputVertices">The polygon vertices in counter-clockwise winding order.</param> /// <param name="desiredWindingOrder">The desired output winding order.</param> /// <param name="outputVertices">The resulting vertices that include any reversals of winding order and holes.</param> /// <param name="indices">The resulting indices for rendering the shape as a triangle list.</param> public static void Triangulate( Vector2[] inputVertices, WindingOrder desiredWindingOrder, out Vector2[] outputVertices, out int[] indices) { Log("\nBeginning triangulation..."); List<Triangle> triangles = new List<Triangle>(); //make sure we have our vertices wound properly if (DetermineWindingOrder(inputVertices) == WindingOrder.Clockwise) { outputVertices = ReverseWindingOrder(inputVertices); System.Console.WriteLine(WindingOrder.Clockwise.ToString()); } else { outputVertices = (Vector2[])inputVertices.Clone(); System.Console.WriteLine(WindingOrder.CounterClockwise.ToString()); } //clear all of the lists polygonVertices.Clear(); earVertices.Clear(); convexVertices.Clear(); reflexVertices.Clear(); //generate the cyclical list of vertices in the polygon for (int i = 0; i < outputVertices.Length; i++) polygonVertices.AddLast(new Vertex(outputVertices[i], i)); //categorize all of the vertices as convex, reflex, and ear FindConvexAndReflexVertices(); FindEarVertices(); //clip all the ear vertices while (polygonVertices.Count > 3 && earVertices.Count > 0) ClipNextEar(triangles); //if there are still three points, use that for the last triangle if (polygonVertices.Count == 3) triangles.Add(new Triangle( polygonVertices[0].Value, polygonVertices[1].Value, polygonVertices[2].Value)); //add all of the triangle indices to the output array indices = new int[triangles.Count * 3]; //move the if statement out of the loop to prevent all the //redundant comparisons if (desiredWindingOrder == WindingOrder.CounterClockwise) { for (int i = 0; i < triangles.Count; i++) { indices[(i * 3)] = triangles[i].A.Index; indices[(i * 3) + 1] = triangles[i].B.Index; indices[(i * 3) + 2] = triangles[i].C.Index; } } else { for (int i = 0; i < triangles.Count; i++) { indices[(i * 3)] = triangles[i].C.Index; indices[(i * 3) + 1] = triangles[i].B.Index; indices[(i * 3) + 2] = triangles[i].A.Index; } } }
// Return the modular distance from one angle to another using the given winding order. public static int GetAngleDistance(int startAngle, int endAngle, WindingOrder windingOrder) { if (windingOrder == WindingOrder.Clockwise) { if (endAngle > startAngle) return (startAngle + Angles.AngleCount - endAngle); else return (startAngle - endAngle); } else { if (endAngle < startAngle) return (endAngle + Angles.AngleCount - startAngle); else return (endAngle - startAngle); } }
public void ControlFlow(string message, object someFoo, WindingOrder windingOrder) // | Use c# aliases of System types (e.g. object instead of Object, float instead of Single, etc.) { for (int i = 0; i < k_MaxCount; ++i) // | Using i and j for trivial local iterators is encouraged { // all of this is nonsense, and is just meant to demonstrate formatting // | Place comments about multiple lines of code directly above them, with one empty line above the comment to visually group it with its code if ((i % -3) - 1 == 0) // | Wrap parens around subexpressions is optional but recommended to make operator precedence clear { ++m_CurrentCount; s_SharedCount *= (int)k_DefaultLength.x + totalCount; do // | 'while', 'do', 'for', 'foreach', 'switch' are always on a separate line from the code block they control { i += s_SharedCount; }while (i < m_CurrentCount); } else // | 'else' always at same indentation level as its 'if' { Debug.LogWarning("Skipping over " + i); // | Drop 'ToString()' when not required by compiler goto skip; // | Goto's not necessarily considered harmful, not disallowed, but should be scrutinized for utility before usage } } skip: // | Goto label targets un-indented from parent scope one tab stop // more nonsense code for demo purposes switch (windingOrder) { case WindingOrder.Clockwise: // | Case labels indented under switch case WindingOrder.CounterClockwise: // | Braces optional if not needed for scope (but note indentation of braces and contents) if (s_SharedCount == DisplayData.MaxItems) // | Constants go on the right in comparisons (do not follow 'yoda' style) { var warningDetails = someFoo.ToString(); // | 'var' for the result of assignments is optional (either way, good variable naming is most important) for (var i = 0; i < s_SharedCount; ++i) { Debug.LogWarning("Spinning a " + warningDetails); } } break; // | 'break' inside case braces, if any case WindingOrder.Charm: Debug.LogWarning("Check quark"); // | Indentation is the same, with or without scope braces break; case WindingOrder.Singularity: { var warningDetails = message; // | (this seemingly pointless variable is here solely to require braces on the case statements and show the required formatting) if (message == Registry.ClassesRoot.ToString()) { // Already correct so we don't need to do anything here // | Empty blocks should (a) only be used when it helps readability, (b) always use empty braces (never a standalone semicolon), and (c) be commented as to why the empty block is there } else if (m_CurrentCount > 3) { if (s_SharedCount < 10) // | Braces can only be omitted at the deepest level of nested code { Debug.LogWarning("Singularity! (" + warningDetails + ")"); } } else if (s_SharedCount > 5) // | 'else if' always on same line together { throw new IndexOutOfRangeException(); } else if ((s_SharedCount > 7 && m_CurrentCount != 0) || message == null) // | Always wrap subexpressions in parens when peer precedence is close enough to be ambiguous (e.g. && and || are commonly confused) { throw new NotImplementedException(); } break; } default: throw new InvalidOperationException("What's a " + windingOrder + "?"); } }
/// <summary> /// Ensures that a set of vertices are wound in a particular order, reversing them if necessary. /// </summary> /// <param name="vertices">The vertices of the polygon.</param> /// <param name="windingOrder">The desired winding order.</param> /// <returns>A new set of vertices if the winding order didn't match; otherwise the original set.</returns> public static Vector2[] EnsureWindingOrder(Vector2[] vertices, WindingOrder windingOrder) { if (DetermineWindingOrder(vertices) != windingOrder) { return ReverseWindingOrder(vertices); } return vertices; }
public static FrontFaceDirection To(WindingOrder windingOrder) { switch (windingOrder) { case WindingOrder.Clockwise: return FrontFaceDirection.Cw; case WindingOrder.Counterclockwise: return FrontFaceDirection.Ccw; } throw new ArgumentException("windingOrder"); }
private static extern MeshData FbxNodeGetMeshAttribute(IntPtr node, WindingOrder preferedWindingOrder, bool limitBoneWeights);
public override Vertices GenerateFromInitial(Vector2 initialVertex, float initialExteriorAngle = 0, WindingOrder windingOrder = WindingOrder.CounterClockwise) { return(GenerateAroundCentroid(Vector2.Zero)); }
/// <summary> /// Triangulates a 2D polygon produced the indexes required to render the points as a triangle list. /// </summary> /// <param name="inputVertices">The polygon vertices in counter-clockwise winding order.</param> /// <param name="desiredWindingOrder">The desired output winding order.</param> /// <param name="outputVertices">The resulting vertices that include any reversals of winding order and holes.</param> /// <param name="indices">The resulting indices for rendering the shape as a triangle list.</param> public static void Triangulate( Vector2[] inputVertices, WindingOrder desiredWindingOrder, out Vector2[] outputVertices, out ushort[] indices) { Log("Beginning triangulation..."); List <Triangle> triangles = new List <Triangle>(); //make sure we have our vertices wound properly if (DetermineWindingOrder(inputVertices) == WindingOrder.Clockwise) { outputVertices = ReverseWindingOrder(inputVertices); } else { outputVertices = (Vector2[])inputVertices.Clone(); } //clear all of the lists polygonVertices.Clear(); earVertices.Clear(); convexVertices.Clear(); reflexVertices.Clear(); //generate the cyclical list of vertices in the polygon for (int i = 0; i < outputVertices.Length; i++) { polygonVertices.AddLast(new Vertex(outputVertices[i], (ushort)i)); } //categorize all of the vertices as convex, reflex, and ear FindConvexAndReflexVertices(); FindEarVertices(); //clip all the ear vertices while (polygonVertices.Count > 3 && earVertices.Count > 0) { ClipNextEar(triangles); } //if there are still three points, use that for the last triangle if (polygonVertices.Count == 3) { triangles.Add(new Triangle( polygonVertices[0].Value, polygonVertices[1].Value, polygonVertices[2].Value)); } //add all of the triangle indices to the output array indices = new ushort[triangles.Count * 3]; //move the if statement out of the loop to prevent all the //redundant comparisons if (desiredWindingOrder == WindingOrder.CounterClockwise) { for (int i = 0; i < triangles.Count; i++) { indices[(i * 3)] = triangles[i].A.Index; indices[(i * 3) + 1] = triangles[i].B.Index; indices[(i * 3) + 2] = triangles[i].C.Index; } } else { for (int i = 0; i < triangles.Count; i++) { indices[(i * 3)] = triangles[i].C.Index; indices[(i * 3) + 1] = triangles[i].B.Index; indices[(i * 3) + 2] = triangles[i].A.Index; } } }
public bool Open(string meshFile, WindingOrder order) { if (Context != null) { Context.Dispose(); Context = null; } Context = new VoxelizationContext(); try { IImporter importer = IOFactory.ImporterFactory(meshFile); Context.CurrentMeshFile = meshFile; Context.CurrentMesh = importer.Load(meshFile); } catch (IOException) { Logger.DisplayError("Unable to open the file: " + meshFile); return(false); } Context.Octree = new VoxelizingOctree(Input.OctreeLevels); Context.Octree.GenerateOctree(Context.CurrentMesh); Vector4[] orignalVertices = new Vector4[Context.CurrentMesh.Vertices.Length]; for (int i = 0; i < orignalVertices.Length; i++) { orignalVertices[i] = new Vector4(Context.CurrentMesh.Vertices[i], 1); } int[] originalIndicies = new int[Context.CurrentMesh.Tris.Length * 3]; if (order == WindingOrder.CounterClockwise) { for (int i = 0; i < Context.CurrentMesh.Tris.Length; i++) { Tri t = Context.CurrentMesh.Tris[i]; int index = i * 3; originalIndicies[index + 0] = t.P1.Vertex; originalIndicies[index + 1] = t.P2.Vertex; originalIndicies[index + 2] = t.P3.Vertex; } } else if (order == WindingOrder.Clockwise) { for (int i = 0; i < Context.CurrentMesh.Tris.Length; i++) { Tri t = Context.CurrentMesh.Tris[i]; int index = i * 3; originalIndicies[index + 0] = t.P1.Vertex; originalIndicies[index + 2] = t.P2.Vertex; originalIndicies[index + 1] = t.P3.Vertex; } } if (Context.OriginalMesh != null) { Context.OriginalMesh.Dispose(); Context.OriginalMesh = null; } Mesh mesh = new Mesh(); mesh.Indicies = originalIndicies; mesh.Vertices = orignalVertices; Context.OriginalMesh = new RenderableMesh(mesh, true); return(true); }