internal int AddClonedTriangle(int tiMul3, BspSplitPoint sp0, BspSplitPoint sp1, BspSplitPoint sp2) { AddSplitPoint(tiMul3, sp0); AddSplitPoint(tiMul3, sp1); AddSplitPoint(tiMul3, sp2); int ntiMul3 = TriangleCountMul3; int tcMul3 = ntiMul3 + 3; EnsureTriangleCapacity(tcMul3); TriangleCountMul3 = tcMul3; m_triangleVertexIndexArray[ntiMul3] = sp0.VertexIndex; m_triangleVertexIndexArray[ntiMul3 + 1] = sp1.VertexIndex; m_triangleVertexIndexArray[ntiMul3 + 2] = sp2.VertexIndex; if (m_triangleAttributeIndexArray != null) { m_triangleAttributeIndexArray[ntiMul3 / 3] = m_triangleAttributeIndexArray[tiMul3 / 3]; } return(ntiMul3); }
internal void AddTriangle( BspTreeBuilder builder, int tiMul3, ref Triangle3d tr, V3d normal) { var htr = (V3d.Dot(m_normal, tr.P0 - m_point), V3d.Dot(m_normal, tr.P1 - m_point), V3d.Dot(m_normal, tr.P2 - m_point)); var signs = new[] { htr.Item1, htr.Item2, htr.Item3 }.AggregateSigns(builder.m_absoluteEpsilon); if (signs == Signs.Zero) { m_zeroList.Add(tiMul3); } else if ((signs & Signs.Negative) == Signs.None) { AddTriangle(builder, tiMul3, ref tr, normal, ref m_positiveTree); } else if ((signs & Signs.Positive) == Signs.None) { AddTriangle(builder, tiMul3, ref tr, normal, ref m_negativeTree); } else { // the triangle straddles the separating plane var positivePoints = new List <BspSplitPoint>(4); var negativePoints = new List <BspSplitPoint>(4); V3d firstPoint = tr.P0; double firstHeight = htr.Item1; bool firstPositive = firstHeight > 0.0; if (firstPositive) { positivePoints.Add(new BspSplitPoint(firstPoint, 0, 0.0)); } else { negativePoints.Add(new BspSplitPoint(firstPoint, 0, 0.0)); } V3d startPoint = firstPoint; double startHeight = firstHeight; bool startPositive = firstPositive; int start = 0; int end = 1; while (end < 3) { V3d endPoint = tr[end]; double endHeight = htr.Get(end); bool endPositive = endHeight > 0.0; if (startPositive != endPositive) { V3d direction = endPoint - startPoint; double t = -startHeight / V3d.Dot(m_normal, direction); V3d newPoint = startPoint + t * direction; // note, that the same split point (reference!) is // added to both lists! var sp = new BspSplitPoint(newPoint, start, t); positivePoints.Add(sp); negativePoints.Add(sp); } if (endPositive) { positivePoints.Add(new BspSplitPoint(endPoint, end, 0.0)); } else { negativePoints.Add(new BspSplitPoint(endPoint, end, 0.0)); } start = end; startPoint = endPoint; startHeight = endHeight; startPositive = endPositive; end++; } if (startPositive != firstPositive) { V3d direction = firstPoint - startPoint; double t = -startHeight / V3d.Dot(m_normal, direction); V3d newPoint = startPoint + t * direction; var sp = new BspSplitPoint(newPoint, start, t); positivePoints.Add(sp); negativePoints.Add(sp); } // in order to ensure that all fragments of a triangle are // consecutively stored, we walk through the two point lists // twice. for this we need a store of the triangle indices int[] positiveIndices = new int[2]; int[] negativeIndices = new int[2]; // first pass: generate the cloned triangles (fragments) and // the resulting triangle indices if (positivePoints.Count > 2) { for (int i = 1; i < positivePoints.Count - 1; i++) { positiveIndices[i - 1] = builder.AddClonedTriangle(tiMul3, positivePoints[0], positivePoints[i], positivePoints[i + 1]); } } if (negativePoints.Count > 2) { for (int i = 1; i < negativePoints.Count - 1; i++) { negativeIndices[i - 1] = builder.AddClonedTriangle(tiMul3, negativePoints[0], negativePoints[i], negativePoints[i + 1]); } } // second pass: add the fragments (with the triangle // indices) to the BSP-tree if (positivePoints.Count > 2) { for (int i = 0; i < positivePoints.Count - 2; i++) { AddTriangle(builder, positiveIndices[i], ref m_positiveTree); } } if (negativePoints.Count > 2) { for (int i = 0; i < negativePoints.Count - 2; i++) { AddTriangle(builder, negativeIndices[i], ref m_negativeTree); } } } }
internal void AddSplitPoint(int tiMul3, BspSplitPoint sp) { if (sp.VertexIndex >= 0) { return; // already inserted } if (sp.Parameter == 0.0) { sp.VertexIndex = m_triangleVertexIndexArray[tiMul3 + sp.TriangleVertexIndex]; return; } int vi = VertexCount; int vc = vi + 1; EnsureVertexCapacity(vc); VertexCount = vc; int vi0 = m_triangleVertexIndexArray[tiMul3 + sp.TriangleVertexIndex]; int vi1 = m_triangleVertexIndexArray[tiMul3 + (sp.TriangleVertexIndex + 1) % 3]; V3d p0 = m_positionArray[vi0]; m_positionArray[vi] = p0 + sp.Parameter * (m_positionArray[vi1] - p0); int wc = 0; int dvi0 = vi0 - m_originalVertexCount; wc += dvi0 < 0 ? 1 : m_weightsArray[dvi0].Length; int dvi1 = vi1 - m_originalVertexCount; wc += dvi1 < 0 ? 1 : m_weightsArray[dvi1].Length; var weights = new WeightedIndex[wc]; var invParam = 1.0 - sp.Parameter; wc = 0; if (dvi0 < 0) { weights[wc++] = new WeightedIndex(invParam, vi0); } else { foreach (var widx in m_weightsArray[dvi0]) { weights[wc++] = new WeightedIndex(invParam * widx.Weight, widx.Index); } } if (dvi1 < 0) { weights[wc++] = new WeightedIndex(sp.Parameter, vi1); } else { foreach (var widx in m_weightsArray[dvi1]) { weights[wc++] = new WeightedIndex(sp.Parameter * widx.Weight, widx.Index); } } m_weightsArray[vi - m_originalVertexCount] = weights; sp.VertexIndex = vi; }