예제 #1
0
        /// <summary>
        /// Create the material from another material instance.
        /// </summary>
        /// <param name="other">Other material to clone.</param>
        public SkinnedMaterial(SkinnedMaterial other)
        {
            _effect = other._effect.Clone() as SkinnedEffect;
            MaterialAPI asBase = this;

            other.CloneBasics(ref asBase);
        }
예제 #2
0
        /// <summary>
        /// Draw this model.
        /// </summary>
        /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
        public override void DoEntityDraw(ref Matrix worldTransformations)
        {
            // call base draw entity
            base.DoEntityDraw(ref worldTransformations);

            // reset last radius
            _lastRadius = 0f;
            float scaleLen = worldTransformations.Scale.Length();

            // iterate model meshes
            foreach (var mesh in Model.Meshes)
            {
                // iterate over mesh effects and apply them (set world matrix etc)
                foreach (var effect in mesh.Effects)
                {
                    Materials.MaterialAPI material = effect.GetMaterial();
                    material.Apply(ref worldTransformations, ref _lastBoundingSphere);
                }

                // update last radius
                _lastRadius = System.Math.Max(_lastRadius, mesh.BoundingSphere.Radius * scaleLen);

                // draw the mesh itself
                mesh.Draw();
            }
        }
예제 #3
0
        /// <summary>
        /// Add array of vertices to the combined mesh.
        /// </summary>
        /// <param name="vertices">Vertices array to add.</param>
        /// <param name="indexes">Draw order / indexes array.</param>
        /// <param name="material">Material to use with the vertices.</param>
        public void AddVertices(VertexType[] vertices, ushort[] indexes, Materials.MaterialAPI material)
        {
            // sanity check - if build was called assert
            if (_wasBuilt)
            {
                throw new Exceptions.InvalidActionException("Cannot add vertices to Combined Mesh Entity after it was built!");
            }

            // get the combined chunk to add these vertices to
            CombinedMeshesPart combinedPart = GetCombinedPart(material);

            // add vertices to combined part
            combinedPart.Vertices.AddRange(vertices);
            foreach (var vertex in vertices)
            {
                _allPoints.Add(GetPosition(vertex));
            }

            // set indexes
            combinedPart.PushIndexes(indexes);

            // increase index offset in combined part
            combinedPart.IndexOffset += vertices.Length;

            // update primitives count
            combinedPart.PrimitiveCount += indexes.Length / 3;
        }
예제 #4
0
        /// <summary>
        /// Create the material from another material instance.
        /// </summary>
        /// <param name="other">Other material to clone.</param>
        public BasicMaterial(BasicMaterial other)
        {
            _effect = other._effect.Clone() as BasicEffect;
            MaterialAPI asBase = this;

            other.CloneBasics(ref asBase);
        }
예제 #5
0
        /// <summary>
        /// Create the material from another material instance.
        /// </summary>
        /// <param name="other">Other material to clone.</param>
        public SkyboxMaterial(SkyboxMaterial other)
        {
            _effect = other._effect.Clone() as BasicEffect;
            MaterialAPI asBase = this;

            other.CloneBasics(ref asBase);
            FlipYZ = other.FlipYZ;
        }
예제 #6
0
        /// <summary>
        /// Draw this model.
        /// </summary>
        /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
        public override void DoEntityDraw(ref Matrix worldTransformations)
        {
            // call base draw entity
            base.DoEntityDraw(ref worldTransformations);

            // decompose transformations
            Vector3 position; Quaternion rotation; Vector3 scale;

            worldTransformations.Decompose(out scale, out rotation, out position);

            // add position offset
            position += PositionOffset;

            // create a new world matrix for the billboard
            Matrix newWorld;

            // if facing camera, create billboard world matrix
            if (FaceCamera)
            {
                // set rotation based on camera with locked axis
                if (LockedAxis != null)
                {
                    newWorld = Matrix.CreateScale(scale) *
                               Matrix.CreateConstrainedBillboard(position, GraphicsManager.ActiveCamera.Position,
                                                                 LockedAxis.Value, null, null);
                }
                // set rotation based on camera without any locked axis
                else
                {
                    newWorld = Matrix.CreateScale(scale) *
                               Matrix.CreateBillboard(position, GraphicsManager.ActiveCamera.Position,
                                                      Vector3.Up, null);
                }
            }
            // if not facing camera, just use world transformations
            else
            {
                newWorld = worldTransformations;
            }

            // update per-entity override properties
            Materials.MaterialAPI material = MaterialOverride.Apply(Material);

            // setup material
            material.Apply(ref newWorld, ref _lastBoundingSphere);

            // draw sprite
            // draw the cube vertices
            material.IterateEffectPasses((EffectPass pass) =>
            {
                GraphicsManager.GraphicsDevice.DrawUserIndexedPrimitives
                <VertexPositionNormalTexture>(
                    PrimitiveType.TriangleList,
                    _spritesheetStep.Vertices, 0, 4,
                    _spritesheetStep.Indexes, 0, 2);
            });
        }
예제 #7
0
        /// <summary>
        /// Create the material from another material instance.
        /// </summary>
        /// <param name="other">Other material to clone.</param>
        public AlphaTestMaterial(AlphaTestMaterial other)
        {
            _effect = other._effect.Clone() as AlphaTestEffect;
            MaterialAPI asBase = this;

            other.CloneBasics(ref asBase);
            AlphaFunction  = other.AlphaFunction;
            ReferenceAlpha = other.ReferenceAlpha;
        }
예제 #8
0
        /// <summary>
        /// Create the material from another material instance.
        /// </summary>
        /// <param name="other">Other material to clone.</param>
        public LitMaterial(LitMaterial other)
        {
            // clone effect and set defaults
            _effect = other._effect.Clone();
            MaterialAPI asBase = this;
            other.CloneBasics(ref asBase);

            // init light params
            InitLightParams();
        }
예제 #9
0
        /// <summary>
        /// Create the sprite entity.
        /// </summary>
        /// <param name="spritesheet">Spritesheet for this sprite.</param>
        /// <param name="material">Material to use for this sprite.</param>
        public SpriteEntity(SpriteSheet spritesheet, Materials.MaterialAPI material) : base()
        {
            // store spritesheet and material
            Spritesheet = spritesheet;
            _material   = material;

            // set default rendering queue
            RenderingQueue = RenderingQueue.Billboards;

            // set default step
            _spritesheetStep = spritesheet.GetStep(0);
        }
예제 #10
0
 /// <summary>
 /// Clone all the basic properties of a material.
 /// </summary>
 /// <param name="cloned">Cloned material to copy properties into.</param>
 protected void CloneBasics(ref MaterialAPI cloned)
 {
     cloned.World          = World;
     cloned.TextureEnabled = TextureEnabled;
     cloned.Texture        = Texture;
     cloned.Alpha          = Alpha;
     cloned.DiffuseColor   = DiffuseColor;
     cloned.SpecularColor  = SpecularColor;
     cloned.SpecularPower  = SpecularPower;
     cloned.AmbientLight   = AmbientLight;
     cloned.EmissiveLight  = EmissiveLight;
     cloned.SamplerState   = SamplerState;
 }
예제 #11
0
        /// <summary>
        /// Apply all custom render properties on a given material, and return either the given material or a clone of it, if needed.
        /// This will not do anything if there are no custom properties currently used.
        /// </summary>
        /// <param name="material">Effect to set properties.</param>
        /// <returns>Either the input material or a clone of it with applied properties.</returns>
        public Materials.MaterialAPI Apply(Materials.MaterialAPI material)
        {
            // if there's nothing to do just return the original material
            if (!UsingOverrideProperties)
            {
                _materialsCahce.Clear();
                return(material);
            }

            // we need to apply custom properties. get the cached material with properties or create a new one
            Materials.MaterialAPI original = material;
            if (!_materialsCahce.TryGetValue(material, out material))
            {
                material = original.Clone();
                _materialsCahce[original] = material;
            }

            // if got override diffuse color, set it
            if (DiffuseColor != null)
            {
                material.DiffuseColor = DiffuseColor.Value;
            }

            // if got override specular color, set it
            if (SpecularColor != null)
            {
                material.SpecularColor = SpecularColor.Value;
            }

            // if got override emissive color, set it
            if (EmissiveLight != null)
            {
                material.EmissiveLight = EmissiveLight.Value;
            }

            // if got override alpha, set it
            if (Alpha != null)
            {
                material.Alpha = Alpha.Value;
            }

            // if got override texture, set it
            if (Texture != null)
            {
                material.Texture        = Texture;
                material.TextureEnabled = true;
            }

            // return the cloned material
            return(material);
        }
예제 #12
0
        /// <summary>
        /// Add a model to the combined mesh.
        /// </summary>
        /// <param name="model">Model to add.</param>
        /// <param name="transform">World transformations.</param>
        /// <param name="material">Optional material to use instead of the model default materials.</param>
        public void AddModel(Model model, Matrix transform, Materials.MaterialAPI material = null)
        {
            // sanity check - if build was called assert
            if (_wasBuilt)
            {
                throw new Exceptions.InvalidActionException("Cannot add model to Combined Mesh Entity after it was built!");
            }

            // iterate model meshes and add them
            foreach (var mesh in model.Meshes)
            {
                AddModelMesh(mesh, transform, material);
            }
        }
예제 #13
0
        /// <summary>
        /// Get combined mesh part from material.
        /// </summary>
        /// <param name="material">Material to get combined part for.</param>
        /// <returns>Combined mesh part.</returns>
        private CombinedMeshesPart GetCombinedPart(Materials.MaterialAPI material)
        {
            // try to get from existing parts and if not found create it
            CombinedMeshesPart combinedPart;

            if (!_parts.TryGetValue(material, out combinedPart))
            {
                combinedPart     = new CombinedMeshesPart();
                _parts[material] = combinedPart;
            }

            // return combined part
            return(combinedPart);
        }
예제 #14
0
        /// <summary>
        /// Return a list with all materials in model.
        /// Note: if alternative materials are set, will return them.
        /// Note2: prevent duplications, eg if even if more than one part uses the same material it will only return it once.
        /// </summary>
        /// <returns>List of materials.</returns>
        public List <Materials.MaterialAPI> GetMaterials()
        {
            List <Materials.MaterialAPI> ret = new List <Materials.MaterialAPI>();

            foreach (var mesh in Model.Meshes)
            {
                for (int i = 0; i < mesh.MeshParts.Count; ++i)
                {
                    Materials.MaterialAPI material = GetMaterial(mesh.Name, i);
                    if (!ret.Contains(material))
                    {
                        ret.Add(material);
                    }
                }
            }
            return(ret);
        }
예제 #15
0
        /// <summary>
        /// Apply all new properties on the material effect.
        /// Call this whenever you want to draw using this material.
        /// </summary>
        /// <param name="worldMatrix">The world transformations of the currently rendered entity.</param>
        /// <param name="boundingSphere">The bounding sphere (should be already transformed) of the rendered entity.</param>
        public void Apply(ref Matrix worldMatrix, ref BoundingSphere boundingSphere)
        {
            // set world matrix
            World = worldMatrix;

            // apply sampler state
            ApplySamplerState();

            // update view if needed
            if (_viewMatrixVersion != _globalViewMatrixVersion)
            {
                UpdateView(ref _view);
                _viewMatrixVersion = _globalViewMatrixVersion;
            }

            // update projection if needed
            if (_projectionMatrixVersion != _globalProjectionMatrixVersion)
            {
                UpdateProjection(ref _projection);
                _projectionMatrixVersion = _globalProjectionMatrixVersion;
            }

            // if support light get lights and set them
            if (LightingEnabled && UseDefaultLightsManager)
            {
                // get lights in rendering range
                var lightsManager = GraphicsManager.ActiveLightsManager;
                var lights        = lightsManager.GetLights(this, ref boundingSphere, MaxLights);
                AmbientLight = lightsManager.AmbientLight;
                ApplyLights(lights, ref worldMatrix, ref boundingSphere);
            }

            // set effect tag to point on self, and call the per-effect specific apply
            if (Effect.Tag == null)
            {
                Effect.Tag = this;
            }
            MaterialSpecificApply(_lastMaterialApplied == this);

            // set last material applied to self
            _lastMaterialApplied = this;

            // clear flags
            _dirtyFlags = 0;
        }
예제 #16
0
        /// <summary>
        /// Return a list with all materials in model.
        /// Note: if alternative materials are set, will return them.
        /// Note2: prevent duplications, eg if even if more than one part uses the same material it will only return it once.
        /// </summary>
        /// <returns>List of materials.</returns>
        public List <Materials.MaterialAPI> GetMaterials()
        {
            List <Materials.MaterialAPI> ret = new List <Materials.MaterialAPI>();

            foreach (DictionaryEntry entry in _meshes)
            {
                MeshEntity mesh = entry.Value as MeshEntity;
                for (int i = 0; i < mesh.Mesh.MeshParts.Count; ++i)
                {
                    Materials.MaterialAPI material = mesh.GetMaterial(i);
                    if (!ret.Contains(material))
                    {
                        ret.Add(material);
                    }
                }
            }
            return(ret);
        }
예제 #17
0
        /// <summary>
        /// Draw this model.
        /// </summary>
        /// <param name="worldTransformations">World transformations to apply on this entity (this is what you should use to draw this entity).</param>
        public override void DoEntityDraw(ref Matrix worldTransformations)
        {
            // call base draw entity
            base.DoEntityDraw(ref worldTransformations);

            // reset last radius
            _lastRadius = 0f;
            float scaleLen = Utils.ExtendedMath.GetScale(ref worldTransformations).Length();

            // iterate model meshes
            foreach (var mesh in Model.Meshes)
            {
                // check if in this mesh we have shared materials, eg same effects used for several mesh parts
                bool gotSharedEffects = mesh.Effects.Count != mesh.MeshParts.Count;

                // iterate over mesh parts
                int index = 0;
                foreach (var meshPart in mesh.MeshParts)
                {
                    // get material for this mesh and effect index
                    Materials.MaterialAPI material = GetMaterial(mesh.Name, index);

                    // no material found? skip.
                    // note: this can happen if user set alternative materials array with less materials than original mesh file
                    if (material == null)
                    {
                        break;
                    }

                    // update per-entity override properties
                    material = MaterialOverride.Apply(material);

                    // if we don't have shared effects, eg every mesh part has its own effect, update material transformations
                    if (!gotSharedEffects)
                    {
                        material.Apply(ref worldTransformations, ref _lastBoundingSphere);
                    }

                    // apply material effect on the mesh part. note: we first store original effect in mesh part's tag.
                    meshPart.Tag    = meshPart.Effect;
                    meshPart.Effect = material.Effect;

                    // next index.
                    ++index;
                }

                // if we have shared effects, eg more than one mesh part with the same effect, we apply all materials here
                // this is to prevent applying the same material more than once
                if (gotSharedEffects)
                {
                    foreach (var effect in mesh.Effects)
                    {
                        effect.GetMaterial().Apply(ref worldTransformations, ref _lastBoundingSphere);
                    }
                }

                // update last radius
                _lastRadius = System.Math.Max(_lastRadius, mesh.BoundingSphere.Radius * scaleLen);

                // iterate mesh parts
                if (ProcessMeshParts)
                {
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        // call the before-drawing-mesh-part callback
                        BeforeDrawingMeshPart(part);
                    }
                }

                // draw the mesh itself
                mesh.Draw();

                // restore original effect to mesh parts
                foreach (var meshPart in mesh.MeshParts)
                {
                    meshPart.Effect = meshPart.Tag as Effect;
                    meshPart.Tag    = null;
                }
            }
        }
예제 #18
0
 /// <summary>
 /// Set alternative material for a specific mesh id.
 /// </summary>
 /// <param name="material">Material to set.</param>
 /// <param name="meshId">Mesh name. If empty string is provided, this material will be used for all meshes.</param>
 public void SetMaterial(Materials.MaterialAPI material, string meshId = "")
 {
     _materials[meshId] = new Materials.MaterialAPI[] { material };
 }
예제 #19
0
        /// <summary>
        /// Add array of vertices to the combined mesh.
        /// </summary>
        /// <param name="vertices">Vertices array to add.</param>
        /// <param name="indexes">Draw order / indexes array.</param>
        /// <param name="transform">World transformations.</param>
        /// <param name="material">Material to use with the vertices.</param>
        public void AddVertices(VertexPositionNormalTexture[] vertices, ushort[] indexes, Matrix transform, Materials.MaterialAPI material)
        {
            // sanity check - if build was called assert
            if (_wasBuilt)
            {
                throw new Exceptions.InvalidActionException("Cannot add vertices to Combined Mesh Entity after it was built!");
            }

            // if transform is identity skip everything here
            if (transform == Matrix.Identity)
            {
                AddVertices(vertices, indexes, material);
                return;
            }

            // transform all vertices from array
            int i = 0;

            VertexPositionNormalTexture[] processed = new VertexPositionNormalTexture[vertices.Length];
            foreach (var vertex in vertices)
            {
                // get current vertex
                VertexPositionNormalTexture curr = vertex;

                // apply transformations
                curr.Position  = Vector3.Transform(curr.Position, transform);
                curr.Normal    = Vector3.Normalize(Vector3.TransformNormal(curr.Normal, transform));
                processed[i++] = curr;
            }

            // add processed vertices
            AddVertices(processed, indexes, material);
        }
예제 #20
0
 /// <summary>
 /// Prepare material to draw this model.
 /// </summary>
 /// <param name="material">Material to prepare.</param>
 /// <param name="world">World transformations.</param>
 protected void PrepareMaterial(Materials.MaterialAPI material, Matrix world)
 {
     // set world / view / projection matrix of the effect
     material.World = world;
 }
예제 #21
0
 /// <summary>
 /// Set first alternative material for this mesh (useful for meshes with one effect).
 /// </summary>
 /// <param name="material">Material to set.</param>
 public void SetMaterial(Materials.MaterialAPI material)
 {
     _materials = new Materials.MaterialAPI[] { material };
 }
예제 #22
0
        /// <summary>
        /// Add a model mesh to the combined mesh.
        /// </summary>
        /// <param name="mesh">Mesh to add.</param>
        /// <param name="transform">World transformations.</param>
        /// <param name="material">Optional material to use instead of the mesh default materials.</param>
        public void AddModelMesh(ModelMesh mesh, Matrix transform, Materials.MaterialAPI material = null)
        {
            // sanity check - if build was called assert
            if (_wasBuilt)
            {
                throw new Exceptions.InvalidActionException("Cannot add meshes to Combined Mesh Entity after it was built!");
            }

            // did we get material override to set?
            bool externalMaterial = material != null;

            // iterate mesh parts
            foreach (var meshPart in mesh.MeshParts)
            {
                // if we didn't get external material to use, get material from mesh part.
                if (!externalMaterial)
                {
                    material = meshPart.GetMaterial();
                }

                // get the combined chunk to add this meshpart to
                CombinedMeshesPart combinedPart = GetCombinedPart(material);

                // make sure its not readonly
                if (meshPart.VertexBuffer.BufferUsage == BufferUsage.WriteOnly ||
                    meshPart.IndexBuffer.BufferUsage == BufferUsage.WriteOnly)
                {
                    throw new Exceptions.InvalidValueException("Cannot add mesh with write-only buffers to Combined Mesh!");
                }

                // make sure vertex buffer uses position-normal-texture
                if (meshPart.VertexBuffer.VertexDeclaration.VertexStride < 8)
                {
                    throw new Exceptions.InvalidValueException("Combined meshes can only use vertex buffers with position, normal and texture!");
                }

                // get vertex buffer parameters
                int vertexStride     = meshPart.VertexBuffer.VertexDeclaration.VertexStride;
                int vertexBufferSize = meshPart.NumVertices * vertexStride;

                // get vertex data as float
                float[] vertexData = new float[vertexBufferSize / sizeof(float)];
                meshPart.VertexBuffer.GetData <float>(vertexData);

                // iterate through vertices and add them
                int verticesInPart = 0;
                for (int i = 0; i < vertexBufferSize / sizeof(float); i += vertexStride / sizeof(float))
                {
                    // get curr position with transformations
                    Vector3 currPosition = Vector3.Transform(new Vector3(vertexData[i], vertexData[i + 1], vertexData[i + 2]), transform);

                    // get other vertex properties based on type and add to vertices buffer
                    switch (_vtype)
                    {
                    case VertexTypes.VertexPosition:
                    {
                        // add to buffer
                        var vertexToAdd = new VertexPosition(currPosition);
                        combinedPart.Vertices.Add(ToVertexType(vertexToAdd));
                        break;
                    }

                    case VertexTypes.VertexPositionColor:
                    {
                        // get color
                        Color currColor = new Color(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5], vertexData[i + 6]);

                        // add to buffer
                        var vertexToAdd = new VertexPositionColor(currPosition, currColor);
                        combinedPart.Vertices.Add(ToVertexType(vertexToAdd));
                        break;
                    }

                    case VertexTypes.VertexPositionNormalTexture:
                    {
                        // get normal
                        Vector3 normal = new Vector3(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5]);
                        normal = Vector3.Normalize(Vector3.TransformNormal(normal, transform));

                        // get texture coords
                        Vector2 textcoords = new Vector2(vertexData[i + 6], vertexData[i + 7]);

                        // add to buffer
                        var vertexToAdd = new VertexPositionNormalTexture(currPosition, normal, textcoords);
                        combinedPart.Vertices.Add(ToVertexType(vertexToAdd));
                        break;
                    }

                    case VertexTypes.VertexPositionNormalTangentTexture:
                    {
                        // get normal
                        Vector3 normal = new Vector3(vertexData[i + 3], vertexData[i + 4], vertexData[i + 5]);
                        normal = Vector3.Normalize(Vector3.TransformNormal(normal, transform));

                        // get tangent
                        Vector3 tangent = new Vector3(vertexData[i + 6], vertexData[i + 7], vertexData[i + 8]);

                        // get binormal
                        Vector3 binormal = new Vector3(vertexData[i + 9], vertexData[i + 10], vertexData[i + 11]);

                        // get texture coords
                        Vector2 textcoords = new Vector2(vertexData[i + 12], vertexData[i + 13]);

                        // add to buffer
                        var vertexToAdd = new VertexPositionNormalTangentTexture(currPosition, normal, textcoords, tangent, binormal);
                        combinedPart.Vertices.Add(ToVertexType(vertexToAdd));
                        break;
                    }

                    case VertexTypes.VertexPositionTexture:
                    {
                        // get texture coords
                        Vector2 textcoords = new Vector2(vertexData[i + 3], vertexData[i + 4]);

                        // add to buffer
                        var vertexToAdd = new VertexPositionTexture(currPosition, textcoords);
                        combinedPart.Vertices.Add(ToVertexType(vertexToAdd));
                        break;
                    }

                    default:
                        throw new Exceptions.InternalError("Forgot to implement type support?");
                    }

                    // add to temp list of all points and increase vertices count
                    _allPoints.Add(currPosition);
                    verticesInPart++;
                }

                // set indexes
                ushort[] drawOrder = new ushort[meshPart.IndexBuffer.IndexCount];
                meshPart.IndexBuffer.GetData <ushort>(drawOrder);
                combinedPart.PushIndexes(drawOrder);

                // increase indexes offset
                combinedPart.IndexOffset += verticesInPart;

                // increase primitives count
                combinedPart.PrimitiveCount += meshPart.PrimitiveCount;
            }
        }
예제 #23
0
        /// <summary>
        /// Add array of vertices to the combined mesh.
        /// </summary>
        /// <param name="vertices">Vertices array to add.</param>
        /// <param name="indexes">Draw order / indexes array.</param>
        /// <param name="transform">World transformations.</param>
        /// <param name="material">Material to use with the vertices.</param>
        public void AddVertices(VertexType[] vertices, ushort[] indexes, Matrix transform, Materials.MaterialAPI material)
        {
            // sanity check - if build was called assert
            if (_wasBuilt)
            {
                throw new Exceptions.InvalidActionException("Cannot add vertices to Combined Mesh Entity after it was built!");
            }

            // if transform is identity skip everything here
            if (transform == Matrix.Identity)
            {
                AddVertices(vertices, indexes, material);
                return;
            }

            // transform all vertices from array
            int i = 0;

            VertexType[] processed = new VertexType[vertices.Length];
            foreach (var vertex in vertices)
            {
                // get current vertex
                VertexType curr = vertex;

                // apply transformations
                switch (_vtype)
                {
                case VertexTypes.VertexPosition:
                {
                    var currVer = ToSpecificVertexType <VertexPosition>(curr);
                    currVer.Position = Vector3.Transform(currVer.Position, transform);
                    processed[i++]   = ToVertexType(currVer);
                    break;
                }

                case VertexTypes.VertexPositionColor:
                {
                    var currVer = ToSpecificVertexType <VertexPositionColor>(curr);
                    currVer.Position = Vector3.Transform(currVer.Position, transform);
                    processed[i++]   = ToVertexType(currVer);
                    break;
                }

                case VertexTypes.VertexPositionNormalTexture:
                {
                    var currVer = ToSpecificVertexType <VertexPositionNormalTexture>(curr);
                    currVer.Position = Vector3.Transform(currVer.Position, transform);
                    currVer.Normal   = Vector3.Normalize(Vector3.TransformNormal(currVer.Normal, transform));
                    processed[i++]   = ToVertexType(currVer);
                    break;
                }

                case VertexTypes.VertexPositionNormalTangentTexture:
                {
                    var currVer = ToSpecificVertexType <VertexPositionNormalTangentTexture>(curr);
                    currVer.Position = Vector3.Transform(currVer.Position, transform);
                    currVer.Normal   = Vector3.Normalize(Vector3.TransformNormal(currVer.Normal, transform));
                    currVer.Tangent  = Vector3.Normalize(Vector3.TransformNormal(currVer.Tangent, transform));
                    currVer.Binormal = Vector3.Normalize(Vector3.TransformNormal(currVer.Binormal, transform));
                    processed[i++]   = ToVertexType(currVer);
                    break;
                }

                case VertexTypes.VertexPositionTexture:
                {
                    var currVer = ToSpecificVertexType <VertexPositionTexture>(curr);
                    currVer.Position = Vector3.Transform(currVer.Position, transform);
                    processed[i++]   = ToVertexType(currVer);
                    break;
                }
                }
            }

            // add processed vertices
            AddVertices(processed, indexes, material);
        }