diff --git a/PluginCommon/Interfaces.cs b/PluginCommon/Interfaces.cs index ce7cdc2..857362c 100644 --- a/PluginCommon/Interfaces.cs +++ b/PluginCommon/Interfaces.cs @@ -357,6 +357,8 @@ namespace PluginCommon { IntPair[] GetVertexFaces(); IntPair[] GetEdgeFaces(); + int[] GetExcludedVertices(); + int[] GetExcludedEdges(); } /// diff --git a/PluginCommon/VisWireframe.cs b/PluginCommon/VisWireframe.cs index 10ff9ee..0e94bc0 100644 --- a/PluginCommon/VisWireframe.cs +++ b/PluginCommon/VisWireframe.cs @@ -48,13 +48,18 @@ namespace PluginCommon { private List mVertexFaces = new List(); private List mEdgeFaces = new List(); + private List mExcludedVertices = new List(); + private List mExcludedEdges = new List(); + + /// /// Constructor. Nothing much to do. /// public VisWireframe() { } /// - /// Adds the vertex to the list. + /// Adds the vertex to the list. Coordinates may be INVALID_VERTEX to exclude the + /// vertex from rendering. /// /// X coordinate. /// Y coordinate. @@ -133,6 +138,24 @@ namespace PluginCommon { mEdgeFaces.Add(new IntPair(edgeIndex, faceIndex)); } + /// + /// Marks a vertex as excluded. Used for level-of-detail reduction. + /// + /// Index of vertex. + public void AddVertexExclusion(int vertexIndex) { + Debug.Assert(vertexIndex >= 0); + mExcludedVertices.Add(vertexIndex); + } + + /// + /// Marks an edge as excluded. Used for level-of-detail reduction. + /// + /// Index of edge. + public void AddEdgeExclusion(int edgeIndex) { + Debug.Assert(edgeIndex >= 0); + mExcludedEdges.Add(edgeIndex); + } + /// /// Verifies that the various references by index are valid. /// @@ -185,6 +208,22 @@ namespace PluginCommon { } } + // check excluded vertices + for (int i = 0; i < mExcludedVertices.Count; i++) { + if (mExcludedVertices[i] < 0 || mExcludedVertices[i] >= vertexCount) { + msg = "excluded nonexistent vertex " + i; + return false; + } + } + + // check excluded edges + for (int i = 0; i < mExcludedEdges.Count; i++) { + if (mExcludedEdges[i] < 0 || mExcludedEdges[i] >= edgeCount) { + msg = "excluded nonexistent edge " + i; + return false; + } + } + // TODO(maybe): confirm that every face (i.e. normal) has a vertex we can use for // BFC calculation. Not strictly necessary since you can do orthographic-projection // BFC without it... but who does that? @@ -233,6 +272,14 @@ namespace PluginCommon { return mEdgeFaces.ToArray(); } + public int[] GetExcludedVertices() { + return mExcludedVertices.ToArray(); + } + + public int[] GetExcludedEdges() { + return mExcludedEdges.ToArray(); + } + public override string ToString() { return "[VisWireframe: " + mVerticesX.Count + " vertices, " + diff --git a/SourceGen/WireframeObject.cs b/SourceGen/WireframeObject.cs index 8082ef3..94ef108 100644 --- a/SourceGen/WireframeObject.cs +++ b/SourceGen/WireframeObject.cs @@ -15,10 +15,8 @@ */ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Diagnostics; -using CommonUtil; using PluginCommon; namespace SourceGen { @@ -44,13 +42,14 @@ namespace SourceGen { } private class Vertex { - public List Faces { get; private set; } - public Vector3 Vec { get; private set; } + public List Faces { get; private set; } + public bool IsExcluded { get; private set; } - public Vertex(double x, double y, double z) { + public Vertex(double x, double y, double z, bool isExcluded) { Vec = new Vector3(x, y, z); Faces = new List(); + IsExcluded = isExcluded; } public override string ToString() { @@ -62,11 +61,13 @@ namespace SourceGen { public Vertex Vertex0 { get; private set; } public Vertex Vertex1 { get; private set; } public List Faces { get; private set; } + public bool IsExcluded { get; private set; } - public Edge(Vertex v0, Vertex v1) { + public Edge(Vertex v0, Vertex v1, bool isExcluded) { Vertex0 = v0; Vertex1 = v1; Faces = new List(); + IsExcluded = isExcluded; } } @@ -125,6 +126,7 @@ namespace SourceGen { float[] verticesX = visWire.GetVerticesX(); float[] verticesY = visWire.GetVerticesY(); float[] verticesZ = visWire.GetVerticesZ(); + int[] excludedVertices = visWire.GetExcludedVertices(); if (verticesX.Length == 0) { Debug.Assert(false); return null; @@ -135,10 +137,12 @@ namespace SourceGen { } for (int i = 0; i < verticesX.Length; i++) { - wireObj.mVertices.Add(new Vertex(verticesX[i], verticesY[i], verticesZ[i])); + wireObj.mVertices.Add(new Vertex(verticesX[i], verticesY[i], verticesZ[i], + HasIndex(excludedVertices, i))); } IntPair[] edges = visWire.GetEdges(); + int[] excludedEdges = visWire.GetExcludedEdges(); for (int i = 0; i < edges.Length; i++) { int v0index = edges[i].Val0; int v1index = edges[i].Val1; @@ -149,8 +153,8 @@ namespace SourceGen { return null; } - wireObj.mEdges.Add( - new Edge(wireObj.mVertices[v0index], wireObj.mVertices[v1index])); + wireObj.mEdges.Add(new Edge(wireObj.mVertices[v0index], + wireObj.mVertices[v1index], HasIndex(excludedEdges, i))); } IntPair[] vfaces = visWire.GetVertexFaces(); @@ -206,6 +210,15 @@ namespace SourceGen { return wireObj; } + private static bool HasIndex(int[] arr, int val) { + for (int i = 0; i < arr.Length; i++) { + if (arr[i] == val) { + return true; + } + } + return false; + } + /// /// Generates a list of line segments for the wireframe data and the specified /// parameters. @@ -273,10 +286,11 @@ namespace SourceGen { foreach (Edge edge in mEdges) { if (doBfc) { // To be visible, vertices and edges must either not specify any - // faces, or must specify a visible face. - if (!IsVertexVisible(edge.Vertex0) || - !IsVertexVisible(edge.Vertex1) || - !IsEdgeVisible(edge)) { + // faces, or must specify a visible face. They can also be hidden + // by the level-of-detail exclusion mechanism. + if (!IsVertexVisible(edge.Vertex0) || edge.Vertex0.IsExcluded || + !IsVertexVisible(edge.Vertex1) || edge.Vertex1.IsExcluded || + !IsEdgeVisible(edge) || edge.IsExcluded) { continue; } }