Ejemplo n.º 1
0
        private void ProjectPolygon()
        {
            var norm = _normal;

            bool computedNormal = false;

            if (norm.X == 0.0f && norm.Y == 0.0f && norm.Z == 0.0f)
            {
                ComputeNormal(ref norm);
                computedNormal = true;
            }

            int i = Vec3.LongAxis(ref norm);

            _sUnit [i]           = 0.0f;
            _sUnit [(i + 1) % 3] = SUnitX;
            _sUnit [(i + 2) % 3] = SUnitY;

            _tUnit [i]           = 0.0f;
            _tUnit [(i + 1) % 3] = norm [i] > 0.0f ? -SUnitY : SUnitY;
            _tUnit [(i + 2) % 3] = norm [i] > 0.0f ? SUnitX : -SUnitX;

            // Project the vertices onto the sweep plane
            for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
            {
                Vec3.Dot(ref v._coords, ref _sUnit, out v._s);
                Vec3.Dot(ref v._coords, ref _tUnit, out v._t);
            }
            if (computedNormal)
            {
                CheckOrientation();
            }

            // Compute ST bounds.
            bool first = true;

            for (var v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
            {
                if (first)
                {
                    _bminX = _bmaxX = v._s;
                    _bminY = _bmaxY = v._t;
                    first  = false;
                }
                else
                {
                    if (v._s < _bminX)
                    {
                        _bminX = v._s;
                    }
                    if (v._s > _bmaxX)
                    {
                        _bmaxX = v._s;
                    }
                    if (v._t < _bminY)
                    {
                        _bminY = v._t;
                    }
                    if (v._t > _bmaxY)
                    {
                        _bmaxY = v._t;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        private void ComputeNormal(ref Vec3 norm)
        {
            var v = _mesh._vHead._next;

            var minVal = new float[3] {
                v._coords.X, v._coords.Y, v._coords.Z
            };
            var minVert = new MeshUtils.Vertex[3] {
                v, v, v
            };
            var maxVal = new float[3] {
                v._coords.X, v._coords.Y, v._coords.Z
            };
            var maxVert = new MeshUtils.Vertex[3] {
                v, v, v
            };

            for (; v != _mesh._vHead; v = v._next)
            {
                if (v._coords.X < minVal [0])
                {
                    minVal [0]  = v._coords.X;
                    minVert [0] = v;
                }
                if (v._coords.Y < minVal [1])
                {
                    minVal [1]  = v._coords.Y;
                    minVert [1] = v;
                }
                if (v._coords.Z < minVal [2])
                {
                    minVal [2]  = v._coords.Z;
                    minVert [2] = v;
                }
                if (v._coords.X > maxVal [0])
                {
                    maxVal [0]  = v._coords.X;
                    maxVert [0] = v;
                }
                if (v._coords.Y > maxVal [1])
                {
                    maxVal [1]  = v._coords.Y;
                    maxVert [1] = v;
                }
                if (v._coords.Z > maxVal [2])
                {
                    maxVal [2]  = v._coords.Z;
                    maxVert [2] = v;
                }
            }

            // Find two vertices separated by at least 1/sqrt(3) of the maximum
            // distance between any two vertices
            int i = 0;

            if (maxVal [1] - minVal [1] > maxVal [0] - minVal [0])
            {
                i = 1;
            }
            if (maxVal [2] - minVal [2] > maxVal [i] - minVal [i])
            {
                i = 2;
            }
            if (minVal [i] >= maxVal [i])
            {
                // All vertices are the same -- normal doesn't matter
                norm = new Vec3 {
                    X = 0.0f, Y = 0.0f, Z = 1.0f
                };
                return;
            }

            // Look for a third vertex which forms the triangle with maximum area
            // (Length of normal == twice the triangle area)
            float maxLen2 = 0.0f, tLen2;
            var   v1 = minVert [i];
            var   v2 = maxVert [i];
            Vec3  d1, d2, tNorm;

            Vec3.Sub(ref v1._coords, ref v2._coords, out d1);
            for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
            {
                Vec3.Sub(ref v._coords, ref v2._coords, out d2);
                tNorm.X = d1.Y * d2.Z - d1.Z * d2.Y;
                tNorm.Y = d1.Z * d2.X - d1.X * d2.Z;
                tNorm.Z = d1.X * d2.Y - d1.Y * d2.X;
                tLen2   = tNorm.X * tNorm.X + tNorm.Y * tNorm.Y + tNorm.Z * tNorm.Z;
                if (tLen2 > maxLen2)
                {
                    maxLen2 = tLen2;
                    norm    = tNorm;
                }
            }

            if (maxLen2 <= 0.0f)
            {
                // All points lie on a single line -- any decent normal will do
                norm     = Vec3.Zero;
                i        = Vec3.LongAxis(ref d1);
                norm [i] = 1.0f;
            }
        }