C#/XNA Render Object Transforms Problem

Started by
3 comments, last by MJP 15 years, 3 months ago
Hi, I'm having a bit of a weird rendering problem and I really can't figure out what is going on. I've made a Model class with a Render() function which takes as parameters a Matrix (for world transforms) a Material and an Effect. It works fine on a single model, but when I come to draw a list of objects it doesn't quite work right. For instance, Object 1 will sometimes end up using the transform Matrix that was passed to the Render function of Object 2 (i.e. be rotated the way object 1 should be) and vice versa. I'm obviously not resetting something or setting something I shouldn't be but I can't figure out what. This is my Render function for the Model:


        public void Render(Matrix _RenderMatrix, CoinMaterial _Material, CoinEffect _Effect)
        {
            // Check the model is valid
            if (this.isValid == false)
                return;

            // Apply the object matrix
            _RenderMatrix = ObjectMatrix * _RenderMatrix;

            // TODO: Set the vertex decleration elsewhere
            // VertexPositionNormalTexture vertex format used in temp shader
            BaseGame.GraphicsManager.GraphicsDevice.VertexDeclaration = new VertexDeclaration(BaseGame.GraphicsManager.GraphicsDevice,
                VertexPositionNormalTexture.VertexElements);

            _Effect.SetMaterialParameters(_Material);
            
            _Effect.GetXNAEffect.Begin();

            // Loop through each effect pass
            foreach (EffectPass pass in _Effect.GetXNAEffect.CurrentTechnique.Passes)
            {
                // Begin this pass
                pass.Begin();

                // Render all meshes
                foreach (ModelMesh mesh in InternalXNAModel.Meshes)
                {
                    // Setup the world matrix for each mesh 
                    BaseGame.WorldMatrix = Transforms[mesh.ParentBone.Index] * _RenderMatrix;

                    _Effect.SetMatrixParameters();

                    // Render all mesh parts
                    foreach (ModelMeshPart part in mesh.MeshParts)
                    {
                        // Set the stream source
                        BaseGame.GraphicsManager.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
                        BaseGame.GraphicsManager.GraphicsDevice.Indices = mesh.IndexBuffer;

                        // And render
                        BaseGame.GraphicsManager.GraphicsDevice.DrawIndexedPrimitives(  PrimitiveType.TriangleList,
                                                                                        part.BaseVertex, 0, part.NumVertices,
                                                                                        part.StartIndex, part.PrimitiveCount);
                    }
                } 

                pass.End();
            }

            _Effect.GetXNAEffect.End();
        }



I'll paste the effect Effect.SetMaterialParameters() and Effect.SetMatrixParameters() functions too as I'm thinking it's something to do with them.


        // Set the material parameters for the effect
        public virtual void SetMaterialParameters(CoinMaterial _mat)
        {
            // Set all material properties
            if (_mat != null)
            {
                ambientColor.SetValue(_mat.AmbientColour.ToVector4());
                diffuseColor.SetValue(_mat.DiffuseColour.ToVector4());
                specularColor.SetValue(_mat.SpecularColour.ToVector4());
                specularPower.SetValue(_mat.SpecularPower); // TODO <<< Add specular power to materials
                diffuseTexture.SetValue(_mat.DiffuseTexture);
                //normalTexture = _mat.normalTexture;

            } 
        }

        // Set the Matrix parameters for the shader
        public virtual void SetMatrixParameters()
        {
            if (worldViewProj != null)
                worldViewProj.SetValue(BaseGame.WorldMatrix * BaseGame.ViewMatrix * BaseGame.ProjectionMatrix);
            if (viewProj != null)
                viewProj.SetValue(BaseGame.ViewMatrix * BaseGame.ProjectionMatrix);
            if (world != null)
                world.SetValue(BaseGame.WorldMatrix);
            if (viewInverse != null)
                viewInverse.SetValue(Matrix.Invert(BaseGame.ViewMatrix));
            if (lightDir != null)
                lightDir.SetValue(BaseGame.LightDirection);

            // TODO ^^^^ Add proper lighting
        }


A call example


            TestModel.Render( Matrix.CreateScale(2.0f) * Matrix.CreateTranslation(new Vector3(0.0f, 0.0f, 0.0f)), 
                              TestMaterial,
                              CoinShaders.SimpleShader);


Sorry for the code dump but I didn't really think it would make much sense without most of it. Any help is much appreciated. Thanks.
Advertisement
I've literally spent a large chunk of the last four days banging my head against the wall with this and then I figure it out 20 minutes after posting on here for help.

Thanks to anyone who read this anyway.

The problem was solved by using the Effect.CommitChanges() function after setting the effect parameters in the render loop. I'm not sure if this is the preferred way of doing things it works for me at the moment.
Quote:Original post by Boonio
The problem was solved by using the Effect.CommitChanges() function after setting the effect parameters in the render loop. I'm not sure if this is the preferred way of doing things it works for me at the moment.


Nah that's fine, since you don't want to have to call Effect.Begin and Effect.End multiple times.
So, are you saying that I wouldn't be required to BEGIN and END my effect if I'm using the same one on a different model - Only COMMITCHANGES?

Just a question...
Xy
Well you'll still need to call Begin and End at least once, but you can render as much stuff as you want between those calls.

This topic is closed to new replies.

Advertisement