C# ModelViewMatrix implementation using Stack<Matrix4> vs. Uniform passing

StackOverflow https://stackoverflow.com/questions/22445027

  •  15-06-2023
  •  | 
  •  

سؤال

I'm trying to rewrite my c++ code which implements non-fixed pipeline matrices to C#, using OpenTK. I'm encountering problems, as I don't understand why this code is invalid.

static class ModelView
{
    static private Stack<Matrix4> matrix = new Stack<Matrix4>();
    static public Matrix4 Matrix
    {
        get
        {
            return matrix.Peek();
        }
        set
        {
            matrix.Pop();
            matrix.Push(value);
        }
    }
    static public Matrix4 MatrixNormal
    {
        get
        {
            Matrix4 m = matrix.Peek();
            m.Invert();
            m.Transpose();
            return m;
        }
    }
    static public int Uniform { get; set; }
    static public int UniformNormal { get; set; }

    static private void SetUniforms()
    {
        if (Uniform == -1 || UniformNormal == -1)
            throw new Exception("Projection matrix uniform is uninitialized");
        GL.UniformMatrix4(Uniform, false, ref Matrix);
        GL.UniformMatrix4(UniformNormal, false, ref MatrixNormal);            
    }

    /* stack & matrices manipulating funcs */
}

Visual Studio says that "A property, indexer or dynamic member access may not be passed as an out or ref parameter." on those lines:

GL.UniformMatrix4(Uniform, false, ref Matrix);
GL.UniformMatrix4(UniformNormal, false, ref MatrixNormal);     

Why can't I pass Stack.Peek() as it should be only Object reference.

هل كانت مفيدة؟

المحلول

This is because your Matrix and MatrixNormal is properties and you can't send it as ref parameter you need to use method not properties for them

it is good practice to use properties when you what to /get/set field values or it is some lightweight function but it your case it is better to use a methods here. try this: (put method return values as fields)

public class Matrix
{
    private Stack<Matrix4> matrix = new Stack<Matrix4>();
    Matrix4 peek = null; 
    public Matrix4 Peek()
    {
        peek = matrix.Peek();
        return peek;

    }

    public void Peek(Matrix4 value)
    {
        matrix.Pop();
        matrix.Push(value);

    }
    private Matrix normalMatrix = null;
    public Matrix4 MatrixNormal()
    {
        Matrix4 m = matrix.Peek();
            m.Invert();
            m.Transpose();
            normalMatrix = m;
            return normalMatrix;
    }
    public int Uniform { get; set; }
    public int UniformNormal { get; set; }

     private void SetUniforms()


 {
        if (Uniform == -1 || UniformNormal == -1)
            throw new Exception("Projection matrix uniform is uninitialized");
        Peek();
        MatrixNormal();
        GL.UniformMatrix4(Uniform, false, ref peek);

        GL.UniformMatrix4(UniformNormal, false, ref normalMatrix);            
    }

نصائح أخرى

Parameters passed as ref can be both read and written by the called method. A Property is like an object with a getter and a setter (well, it doesn't need to have both), and one can not assume that the getter and the setter has the same backing field. So it's therefore not possible/allowed to pass a Property as a ref parameter.

The problem is that using a ref parameter, you have to supply what would be considered a pointer in C++. A property won't do, because that is nothing more than a method (or two methods) with some syntactic sugar. A property will give you value, not a memory address.

If you don't want to (or can't) pass your matrix as a ref parameter, you have to use a different overload of GL.UniformMatrix4, for example this:

GL.UniformMatrix4(int location, int count, bool transpose, float[] value)

You just have to convert your Matrix4 object to an array of 16 floats.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top