public ModelVertexMapping GetVertexMappingToGPU(Model modelAsset, IEffect effectAsset)
        {
            switch (effectAsset.Name)
            {
            case "effect.BuiltinSurface:TextureNormalSkinned":
            case "effect.BuiltinSurface:TextureNormalSpecColDefSkinned":
            case "effect.BuiltinSurface:TextureNormalSpecColConSkinned":
            case "effect.BuiltinSurface:TextureNormalSpecColMapSkinned":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalBinormalTangentTextureBlendable(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               src.BiTangent ?? Vector3.Zero,
                               src.Tangent ?? Vector3.Zero,
                               (src.TexCoordsUV != null && src.TexCoordsUV.Length >= 1) ? src.TexCoordsUV[0] : Vector2.Zero,
                               src.BoneWeights ?? Vector4.Zero,
                               src.BoneIndices ?? new Byte4(0, 0, 0, 0))));

            case "effect.BuiltinSurface:TextureSkinned":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalTextureBlendable(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               (src.TexCoordsUV != null && src.TexCoordsUV.Length >= 1) ? src.TexCoordsUV[0] : Vector2.Zero,
                               src.BoneWeights ?? Vector4.Zero,
                               src.BoneIndices ?? new Byte4(0, 0, 0, 0))));

            case "effect.BuiltinSurface:ColorSkinned":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalColorBlendable(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               (src.Colors != null && src.Colors.Length >= 1) ? src.Colors[0]: new Color(),
                               src.BoneWeights ?? Vector4.Zero,
                               src.BoneIndices ?? new Byte4(0, 0, 0, 0))));

            case "effect.BuiltinSurface:DiffuseSkinned":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalBlendable(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               src.BoneWeights ?? Vector4.Zero,
                               src.BoneIndices ?? new Byte4(0, 0, 0, 0))));

            case "effect.BuiltinSurface:TextureNormal":
            case "effect.BuiltinSurface:TextureNormalSpecColDef":
            case "effect.BuiltinSurface:TextureNormalSpecColCon":
            case "effect.BuiltinSurface:TextureNormalSpecColMap":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalBinormalTangentTexture(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               src.BiTangent ?? Vector3.Zero,
                               src.Tangent ?? Vector3.Zero,
                               (src.TexCoordsUV != null && src.TexCoordsUV.Length >= 1) ? src.TexCoordsUV[0] : Vector2.Zero)));

            case "effect.BuiltinSurface:Texture":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalTexture(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               (src.TexCoordsUV != null && src.TexCoordsUV.Length >= 1) ? src.TexCoordsUV[0] : Vector2.Zero)));

            case "effect.BuiltinSurface:Color":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormalColor(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero,
                               (src.Colors != null && src.Colors.Length >= 1) ? src.Colors[0] : new Color())));

            case "effect.BuiltinSurface:Diffuse":
                return(ModelVertexMapping.Create(
                           src => new VertexPositionNormal(
                               src.Position ?? Vector3.Zero,
                               src.Normal ?? Vector3.Zero)));

            case "effect.PointLight":
                return(ModelVertexMapping.Create(
                           src => new VertexPosition(src.Position ?? Vector3.Zero)));

            default:
                return(null);
            }
        }
Пример #2
0
        /// <summary>
        /// Creates a render request for the model using the specified transform.
        /// </summary>
        /// <param name="renderContext">
        ///     The render context.
        /// </param>
        /// <param name="effect"></param>
        /// <param name="effectParameterSet"></param>
        /// <param name="transform">
        ///     The transform.
        /// </param>
        public IRenderRequest CreateRenderRequest(IRenderContext renderContext, IEffect effect, IEffectParameterSet effectParameterSet, Matrix transform)
        {
            if (Vertexes.Length == 0 && Indices.Length == 0)
            {
                throw new InvalidOperationException(
                          "This model does not have any vertexes or indices.  It's most " +
                          "likely been imported from an FBX file that only contains hierarchy, " +
                          "in which case there isn't anything to render.");
            }

            LoadBuffers(renderContext.GraphicsDevice);

            VertexBuffer vertexBuffer;

            if (_cachedVertexBuffers.ContainsKey(effect))
            {
                vertexBuffer = _cachedVertexBuffers[effect];
            }
            else
            {
                // Find the vertex mapping configuration for this model.
                if (_cachedModelVertexMapping == null)
                {
                    _cachedModelVertexMapping =
                        _modelRenderConfigurations.Select(x => x.GetVertexMappingToGPU(this, effect))
                        .FirstOrDefault(x => x != null);
                    if (_cachedModelVertexMapping == null)
                    {
                        throw new InvalidOperationException(
                                  "No implementation of IModelRenderConfiguration could provide a vertex " +
                                  "mapping for this model.  You must implement IModelRenderConfiguration " +
                                  "and bind it in the dependency injection system, so that the engine is " +
                                  "aware of how to map vertices in models to parameters in effects.");
                    }
                }

                var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length);
                for (var i = 0; i < Vertexes.Length; i++)
                {
                    var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i]);
                    mappedVerticies.SetValue(vertex, i);
                }

                float maxX = 0f, maxY = 0f, maxZ = 0f;
                foreach (var vert in this.Vertexes)
                {
                    if (vert.Position.HasValue)
                    {
                        if (Math.Abs(vert.Position.Value.X) > maxX)
                        {
                            maxX = Math.Abs(vert.Position.Value.X);
                        }
                        if (Math.Abs(vert.Position.Value.Y) > maxY)
                        {
                            maxY = Math.Abs(vert.Position.Value.Y);
                        }
                        if (Math.Abs(vert.Position.Value.Z) > maxZ)
                        {
                            maxZ = Math.Abs(vert.Position.Value.Z);
                        }
                    }
                }

                var radius = new Vector3(maxX, maxY, maxZ).Length() * 2;

                _localisedBoundingRegion = new LocalisedBoundingRegion(radius);

                vertexBuffer = new VertexBuffer(
                    renderContext.GraphicsDevice,
                    _cachedModelVertexMapping.VertexDeclaration,
                    Vertexes.Length,
                    BufferUsage.WriteOnly);
                vertexBuffer.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                    vertexBuffer,
                    new[] { mappedVerticies });
                _cachedVertexBuffers[effect] = vertexBuffer;
            }

            if (effectParameterSet.HasSemantic <IBonesEffectSemantic>())
            {
                var bonesEffectSemantic = effectParameterSet.GetSemantic <IBonesEffectSemantic>();

                foreach (var bone in _flattenedBones)
                {
                    if (bone.ID == -1)
                    {
                        continue;
                    }

                    bonesEffectSemantic.Bones[bone.ID] = bone.GetFinalMatrix();
                }
            }

            // Create the render request.
            return(_renderBatcher.CreateSingleRequestFromState(
                       renderContext,
                       effect,
                       effectParameterSet,
                       vertexBuffer,
                       IndexBuffer,
                       PrimitiveType.TriangleList,
                       renderContext.World * transform, (m, vb, ib) =>
            {
                var mappedVerticies = Array.CreateInstance(_cachedModelVertexMapping.VertexType, Vertexes.Length * m.Count);
                var mappedIndicies = new int[Indices.Length * m.Count];

                for (var im = 0; im < m.Count; im++)
                {
                    for (var i = 0; i < Vertexes.Length; i++)
                    {
                        var vertex = _cachedModelVertexMapping.MappingFunction(Vertexes[i].Transform(m[im]));
                        mappedVerticies.SetValue(vertex, im * Vertexes.Length + i);
                    }

                    for (var i = 0; i < Indices.Length; i++)
                    {
                        mappedIndicies[im * Vertexes.Length + i] = Indices[i] + Vertexes.Length * im;
                    }
                }

                vb.GetType().GetMethods().First(x => x.Name == "SetData" && x.GetParameters().Length == 1).MakeGenericMethod(_cachedModelVertexMapping.VertexType).Invoke(
                    vb,
                    new[] { mappedVerticies });
                ib.SetData(mappedIndicies);
            },
                       _localisedBoundingRegion));
        }