/// <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; }
/// <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; }