示例#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);
                _normal        = norm;
                computedNormal = true;
            }

            int i = Vec3.LongAxis(ref norm);

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

            _tUnit[i]           = 0;
            _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;
                    }
                }
            }
        }
示例#2
0
        private void ComputeNormal(ref Vec3 norm)
        {
            var v = _mesh._vHead._next;

            var minVal = new Real[3] {
                v._coords.X, v._coords.Y, v._coords.Z
            };
            var minVert = new MeshUtils.Vertex[3] {
                v, v, v
            };
            var maxVal = new Real[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, Y = 0, Z = 1
                };
                return;
            }

            // Look for a third vertex which forms the triangle with maximum area
            // (Length of normal == twice the triangle area)
            Real maxLen2 = 0, 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;
            }
        }