Ejemplo n.º 1
0
        /// <summary>
        /// Applies a transform to the columns of this <see cref="VertexBufferColumns"/>
        /// </summary>
        /// <param name="transform">A Mesh transformer object</param>
        /// <remarks>
        /// This is a one time operation.
        /// Once it's applied, skinning and morphing columns are removed, since they're baked
        /// into the position, normal and tangent columns.
        /// </remarks>
        public void ApplyTransform(Transforms.IGeometryTransform transform)
        {
            Guard.NotNull(this.Positions, nameof(this.Positions), "Missing Positions column");
            if (this.Normals != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Normals.Count, nameof(this.Normals), ERR_COLUMNLEN);
            }
            if (this.Tangents != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Tangents.Count, nameof(this.Tangents), ERR_COLUMNLEN);
            }
            if (this.Colors0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Colors0.Count, nameof(this.Colors0), ERR_COLUMNLEN);
            }
            if (this.Colors1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Colors1.Count, nameof(this.Colors1), ERR_COLUMNLEN);
            }
            if (this.TexCoords0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords0.Count, nameof(this.TexCoords0), ERR_COLUMNLEN);
            }
            if (this.TexCoords1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords1.Count, nameof(this.TexCoords1), ERR_COLUMNLEN);
            }
            if (this.Joints0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Joints0.Count, nameof(this.Joints0), ERR_COLUMNLEN);
            }
            if (this.Joints1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Joints1.Count, nameof(this.Joints1), ERR_COLUMNLEN);
            }
            if (this.Weights0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Weights0.Count, nameof(this.Weights0), ERR_COLUMNLEN);
            }
            if (this.Weights1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Weights1.Count, nameof(this.Weights1), ERR_COLUMNLEN);
            }

            // since the attributes we want to overwrite might be binded directly to the model's buffer
            // data, and we don't want to modify the source data, we isolate the columns to be overwritten.

            this.Positions = _IsolateColumn(this.Positions);
            this.Normals   = _IsolateColumn(this.Normals);
            this.Tangents  = _IsolateColumn(this.Tangents);
            this.Colors0   = _IsolateColumn(this.Colors0);

            // prepare animation data, if available

            var skinning = default(Transforms.SparseWeight8);

            Vector3[] morphPositions = null;
            Vector3[] morphNormals   = null;
            Vector3[] morphTangents  = null;
            Vector4[] morphColors0   = null;

            if (_MorphTargets != null)
            {
                if (_MorphTargets.All(item => item.Positions != null))
                {
                    morphPositions = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Normals != null))
                {
                    morphNormals = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Tangents != null))
                {
                    morphTangents = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Colors0 != null))
                {
                    morphColors0 = new Vector4[this.MorphTargets.Count];
                }
            }

            // loop over every vertex

            int vcount = this.Positions.Count;

            for (int i = 0; i < vcount; ++i)
            {
                if (this.Joints0 != null)
                {
                    if (this.Joints1 != null)
                    {
                        skinning = new Transforms.SparseWeight8(Joints0[i], Joints1[i], Weights0[i], Weights1[i]);
                    }
                    else
                    {
                        skinning = new Transforms.SparseWeight8(Joints0[i], Weights0[i]);
                    }
                }

                if (this.Positions != null)
                {
                    _FillMorphData(morphPositions, vc => vc.Positions[i]);
                    Positions[i] = transform.TransformPosition(Positions[i], morphPositions, skinning);
                }

                if (this.Normals != null)
                {
                    _FillMorphData(morphNormals, vc => vc.Normals[i]);
                    Normals[i] = transform.TransformNormal(Normals[i], morphNormals, skinning);
                }

                if (this.Tangents != null)
                {
                    _FillMorphData(morphTangents, vc => vc.Tangents[i]);
                    Tangents[i] = transform.TransformTangent(Tangents[i], morphTangents, skinning);
                }

                if (this.Colors0 != null)
                {
                    _FillMorphData(morphColors0, vc => vc.Colors0[i]);
                    Colors0[i] = transform.MorphColors(Colors0[i], morphColors0);
                }
            }

            // we've just applied the transform,
            // so we clear animation columns since
            // they're irrelevant now.

            _MorphTargets = null;

            Joints0  = null;
            Joints1  = null;
            Weights0 = null;
            Weights1 = null;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Applies a transform to the columns of this <see cref="VertexBufferColumns"/>
        /// </summary>
        /// <param name="transform">A Mesh transformer object</param>
        /// <remarks>
        /// This is a one time operation.
        /// Once it's applied, skinning and morphing columns are removed, since they're baked
        /// into the position, normal and tangent columns.
        /// </remarks>
        private void _ApplyTransform(Transforms.IGeometryTransform transform)
        {
            Guard.NotNull(this.Positions, nameof(this.Positions), "Missing Positions column");
            if (this.Normals != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Normals.Count, nameof(this.Normals), ERR_COLUMNLEN);
            }
            if (this.Tangents != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Tangents.Count, nameof(this.Tangents), ERR_COLUMNLEN);
            }
            if (this.Colors0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Colors0.Count, nameof(this.Colors0), ERR_COLUMNLEN);
            }
            if (this.Colors1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Colors1.Count, nameof(this.Colors1), ERR_COLUMNLEN);
            }
            if (this.TexCoords0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords0.Count, nameof(this.TexCoords0), ERR_COLUMNLEN);
            }
            if (this.TexCoords1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords1.Count, nameof(this.TexCoords1), ERR_COLUMNLEN);
            }
            if (this.TexCoords2 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords2.Count, nameof(this.TexCoords2), ERR_COLUMNLEN);
            }
            if (this.TexCoords3 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.TexCoords3.Count, nameof(this.TexCoords3), ERR_COLUMNLEN);
            }
            if (this.Joints0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Joints0.Count, nameof(this.Joints0), ERR_COLUMNLEN);
            }
            if (this.Joints1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Joints1.Count, nameof(this.Joints1), ERR_COLUMNLEN);
            }
            if (this.Weights0 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Weights0.Count, nameof(this.Weights0), ERR_COLUMNLEN);
            }
            if (this.Weights1 != null)
            {
                Guard.IsTrue(this.Positions.Count == this.Weights1.Count, nameof(this.Weights1), ERR_COLUMNLEN);
            }

            // since the attributes we want to overwrite might be bound directly to the model's buffer
            // data, and we don't want to modify the source data, we isolate the columns to be overwritten.

            this.Positions  = _IsolateColumn(this.Positions); // Position, normal and tangent can be modified by morphing and skinning
            this.Normals    = _IsolateColumn(this.Normals);
            this.Tangents   = _IsolateColumn(this.Tangents);
            this.Colors0    = _IsolateColumn(this.Colors0);  // colors0,1 and texCoords0,1 can be modified by morphing
            this.Colors1    = _IsolateColumn(this.Colors1);
            this.TexCoords0 = _IsolateColumn(this.TexCoords0);
            this.TexCoords1 = _IsolateColumn(this.TexCoords1);

            // prepare animation data, if available

            var skinning = default(Transforms.SparseWeight8);

            Transforms.IMaterialTransform morphMaterial = transform as Transforms.IMaterialTransform;

            Vector3[] morphPositions = null;
            Vector3[] morphNormals   = null;
            Vector3[] morphTangents  = null;
            Vector4[] morphColors0   = null;
            Vector4[] morphColors1   = null;
            Vector2[] morphTexcrd0   = null;
            Vector2[] morphTexcrd1   = null;

            if (_MorphTargets != null)
            {
                if (_MorphTargets.All(item => item.Positions != null))
                {
                    morphPositions = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Normals != null))
                {
                    morphNormals = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Tangents != null))
                {
                    morphTangents = new Vector3[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Colors0 != null))
                {
                    morphColors0 = new Vector4[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.Colors1 != null))
                {
                    morphColors1 = new Vector4[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.TexCoords0 != null))
                {
                    morphTexcrd0 = new Vector2[this.MorphTargets.Count];
                }
                if (_MorphTargets.All(item => item.TexCoords1 != null))
                {
                    morphTexcrd1 = new Vector2[this.MorphTargets.Count];
                }
            }

            // loop over every vertex

            int vcount = this.Positions.Count;

            for (int i = 0; i < vcount; ++i)
            {
                if (this.Joints0 != null)
                {
                    if (this.Joints1 != null)
                    {
                        skinning = Transforms.SparseWeight8.Create(Joints0[i], Joints1[i], Weights0[i], Weights1[i]);
                    }
                    else
                    {
                        skinning = Transforms.SparseWeight8.Create(Joints0[i], Weights0[i]);
                    }
                }

                if (this.Positions != null)
                {
                    _FillMorphData(morphPositions, vc => vc.Positions[i]);
                    Positions[i] = transform.TransformPosition(Positions[i], morphPositions, skinning);
                }

                if (this.Normals != null)
                {
                    _FillMorphData(morphNormals, vc => vc.Normals[i]);
                    Normals[i] = transform.TransformNormal(Normals[i], morphNormals, skinning);
                }

                if (this.Tangents != null)
                {
                    _FillMorphData(morphTangents, vc => vc.Tangents[i]);
                    Tangents[i] = transform.TransformTangent(Tangents[i], morphTangents, skinning);
                }

                if (morphMaterial != null)
                {
                    if (this.Colors0 != null)
                    {
                        _FillMorphData(morphColors0, vc => vc.Colors0[i]);
                        Colors0[i] = morphMaterial.MorphColors(Colors0[i], morphColors0);
                    }

                    if (this.Colors1 != null)
                    {
                        _FillMorphData(morphColors1, vc => vc.Colors1[i]);
                        Colors1[i] = morphMaterial.MorphColors(Colors1[i], morphColors1);
                    }

                    if (this.TexCoords0 != null)
                    {
                        _FillMorphData(morphTexcrd0, vc => vc.TexCoords0[i]);
                        TexCoords0[i] = morphMaterial.MorphTexCoord(TexCoords0[i], morphTexcrd0);
                    }

                    if (this.TexCoords1 != null)
                    {
                        _FillMorphData(morphTexcrd1, vc => vc.TexCoords1[i]);
                        TexCoords1[i] = morphMaterial.MorphTexCoord(TexCoords1[i], morphTexcrd1);
                    }
                }
            }

            // we've just applied the transform, so we make this a rigid geometry.

            _MorphTargets = null;

            Joints0  = null;
            Joints1  = null;
            Weights0 = null;
            Weights1 = null;
        }