Пример #1
0
        /// <summary>
        /// Helper function creates a new geometry object,
        /// and sets it to use our billboard effect.
        /// </summary>
        static GeometryContent CreateVegetationGeometry(string textureFilename,
                                                        float width, float height,
                                                        float windAmount,
                                                        ContentIdentity identity)
        {
            GeometryContent geometry = new GeometryContent();

            // Add the vertex channels needed for our billboard geometry.
            VertexChannelCollection channels = geometry.Vertices.Channels;

            // Add a vertex channel holding normal vectors.
            channels.Add <Vector3>(VertexChannelNames.Normal(), null);

            // Add a vertex channel holding texture coordinates.
            channels.Add <Vector2>(VertexChannelNames.TextureCoordinate(0), null);

            // Add a second texture coordinate channel, holding a per-billboard
            // random number. This is used to make each billboard come out a
            // slightly different size, and to animate at different speeds.
            channels.Add <float>(VertexChannelNames.TextureCoordinate(1), null);

            // Create a material for rendering the billboards.
            EffectMaterialContent material = new EffectMaterialContent();

            // Point the material at our custom billboard effect.
            string directory = Path.GetDirectoryName(identity.SourceFilename);

            string effectFilename = Path.Combine(directory, "Billboard.fx");

            material.Effect = new ExternalReference <EffectContent>(effectFilename);

            // Set the texture to be used by these billboards.
            textureFilename = Path.Combine(directory, textureFilename);

            material.Textures.Add("Texture", new ExternalReference <TextureContent>(textureFilename));

            // Set effect parameters describing the size and
            // wind sensitivity of these billboards.
            material.OpaqueData.Add("BillboardWidth", width);
            material.OpaqueData.Add("BillboardHeight", height);
            material.OpaqueData.Add("WindAmount", windAmount);

            geometry.Material = material;

            return(geometry);
        }
        } // Process

        #endregion

        #region Process Vertex Channel

        /// <summary>
        /// Processes geometry content vertex channels at the specified index.
        /// </summary>
        protected override void ProcessVertexChannel(GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            VertexChannelCollection channels = geometry.Vertices.Channels;

            // If the model has only position and normals a UV channel is added.
            // http://xnafinalengine.codeplex.com/wikipage?title=Compressed%20Vertex%20Data
            if (channels.Count == 1 && channels.Contains(VertexChannelNames.Normal()))
            {
                channels.Add<Vector2>(VertexChannelNames.TextureCoordinate(0), null);
            }

            // If the model has position, normal and UV then the data is packed on 32 bytes aliagned vertex data.
            if (channels.Count == 2 && channels.Contains(VertexChannelNames.Normal()) && channels.Contains(VertexChannelNames.TextureCoordinate(0)))
            {
                // No compressed Vertex Data
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
            else // If not then the data is compressed.
            {
                string name = channels[vertexChannelIndex].Name;

                if (name == VertexChannelNames.Normal())
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.TextureCoordinate(0))
                {
                    // Clamp values.
                    /*for (int i = 0; i < channels[vertexChannelIndex].Count; i++)
                    {
                        Vector2 uv = (Vector2)channels[vertexChannelIndex][i];
                        if (uv.X < 0) 
                            uv.X *= -1;
                        if (uv.Y < 0) 
                            uv.Y *= -1;
                        Vector2 uvCampled = new Vector2(uv.X - (float)Math.Truncate(uv.X), uv.Y - (float)Math.Truncate(uv.Y));
                        channels[vertexChannelIndex][i] = uvCampled;
                    }
                    // If the resource has texture coordinates outside the range [-1, 1] the values will be clamped.
                    channels.ConvertChannelContent<NormalizedShort2>(vertexChannelIndex);*/
                    // Sometimes you can't just clamp values, because the distance between vertices surpass 1 uv unit.
                    // And given that I am not removing the binormals I won't normalize the UVs.
                    channels.ConvertChannelContent<HalfVector2>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.TextureCoordinate(1))
                    channels.Remove(VertexChannelNames.TextureCoordinate(1));
                else if (name == VertexChannelNames.TextureCoordinate(2))
                    channels.Remove(VertexChannelNames.TextureCoordinate(2));
                else if (name == VertexChannelNames.TextureCoordinate(3))
                    channels.Remove(VertexChannelNames.TextureCoordinate(3));
                else if (name == VertexChannelNames.TextureCoordinate(4))
                    channels.Remove(VertexChannelNames.TextureCoordinate(4));
                else if (name == VertexChannelNames.TextureCoordinate(5))
                    channels.Remove(VertexChannelNames.TextureCoordinate(5));
                else if (name == VertexChannelNames.TextureCoordinate(6))
                    channels.Remove(VertexChannelNames.TextureCoordinate(6));
                else if (name == VertexChannelNames.TextureCoordinate(7))
                    channels.Remove(VertexChannelNames.TextureCoordinate(7));
                else if (name == VertexChannelNames.Color(0))
                    channels.Remove(VertexChannelNames.Color(0));
                else if (name == VertexChannelNames.Tangent(0))
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                }
                else if (name == VertexChannelNames.Binormal(0))
                {
                    channels.ConvertChannelContent<NormalizedShort4>(vertexChannelIndex);
                    // If the binormal is removed then the position, the normal,
                    // the tangent and one texture coordinate can be fetched in one single block of 32 bytes.
                    // Still, it is more fast to just pass the value. At least on the test I made.
                    //channels.Remove(VertexChannelNames.Binormal(0));
                }
                else
                {
                    base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
                }
            }
        } // ProcessVertexChannel