예제 #1
0
        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);
        }
예제 #2
0
        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);
                    }
                }
            }
        }
예제 #3
0
        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;
        }