Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
HLSL Swizzle-in C#_C#_Swizzling - Fatal编程技术网

HLSL Swizzle-in C#

HLSL Swizzle-in C#,c#,swizzling,C#,Swizzling,我正在寻找一种方法来实现C#中HLSL中的swizzle功能,对于那些不熟悉这是什么的人来说——它用于方便的向量元素访问 Vector4 v1, v2; // (t,x,y,z) or (alpha,r,g,b) v1 = new Vector4 (1,2,0,0); v2 = new Vector4 (0,0,3,4); // v1 (Green, Z) = v2 (Y, Blue) v1.gz = v2.yb; // Result : v1 = (1,2,3,4) 可以创建许多属性(每

我正在寻找一种方法来实现C#中HLSL中的swizzle功能,对于那些不熟悉这是什么的人来说——它用于方便的向量元素访问

Vector4  v1, v2;
// (t,x,y,z) or (alpha,r,g,b)
v1 = new Vector4 (1,2,0,0);
v2 = new Vector4 (0,0,3,4);

// v1 (Green, Z) = v2 (Y, Blue)
v1.gz = v2.yb;
// Result : v1 = (1,2,3,4)
可以创建许多属性(每个可能的组合一个属性)。我有一种感觉,这可能是通过Linq实现的,但我并没有太多的经验

我不知道XNA是否有类似的类型,但我不想走这条路,因为这就是我使用它的全部目的,也就是说,如果它有

谢谢。

在C#3.5及更早版本中,最好的选择是简单地使用一整套属性

然而,在C#4.0中,您可以使用
dynamic
键入和子类
DynamicObject
来获得所需的功能。这可能是一个更好的选择,也可能不是,我对这个功能不太了解

编辑:

我对这个问题非常感兴趣,于是我去实现了一个C#4.0解决方案。代码如下,但您也可以[]。和往常一样,你可以随意使用/破解/制作此代码,只是如果它删除了你的硬盘,不要怪我

编辑3: 这是我将在这里进行的最后一次编辑,但我可能会更多地使用它,我将为稍后来到这里的任何人更新链接版本

编辑2:

在我让您了解代码之前,有一些示例说明了在代码本身的
Program.Main()
中什么将起作用,什么将不起作用

现在,我们来看看代码

namespace Swizzle
{
    /// <summary>
    /// This implements the Vector4 class as described in the question, based on our totally generic
    /// Vector class.
    /// </summary>
    class Vector4 : Vector<int>
    {
        public Vector4(int val0, int val1, int val2, int val3)
            : base(new Dictionary<char, int> { {'t', 0}, {'x', 1}, {'y', 2}, {'z', 3},
                                               {'a', 0}, {'r', 1}, {'g', 2}, {'b', 3}},
                   new int[] { val0, val1, val2, val3 })
        { }
    }

    class Program
    {
        static void Main(string[] args)
        {
            dynamic v1, v2, v3;

            v1 = new Vector4(1, 2, 3, 4);

            v2 = v1.rgb;
            // Prints: v2.r: 2
            Console.WriteLine("v2.r: {0}", v2.r);
            // Prints: red: 2
            int red = v2.r;
            Console.WriteLine("red: {0}", red);
            // Prints: v2 has 3 elements.
            Console.WriteLine("v2 has {0} elements.", v2.Length);

            v3 = new Vector4(5, 6, 7, 8);
            v3.ar = v2.gb; // yes, the names are preserved! v3 = (3, 4, 7, 8)

            v2.r = 5;
            //v2.a = 5; // fails: v2 has no 'a' element, only 'r', 'g', and 'b'

            // Something fun that will also work
            Console.WriteLine("v3.gr: {0}", v3.gr);
            v3.rg = v3.gr; // switch green and red
            Console.WriteLine("v3.gr: {0}", v3.gr);

            Console.WriteLine("\r\nPress any key to continue.");
            Console.ReadKey(true);
        }
    }

    class Vector<T> : DynamicObject
    {
        private T[] m_values;
        private Dictionary<char, int> m_positions;

        public Vector(Dictionary<char, int> positions, params T[] values)
        {
            this.m_positions = positions;
            this.m_values = values;
        }

        public T this[int index] {
            get { return this.m_values[index]; }
        }

        public int Length
        {
            get { return this.m_values.Length; }
        }

        public override string ToString()
        {
            List<string> elements = new List<string>(this.Length);

            for (int i = 0; i < this.Length; i++)
            {
                elements.Add(m_values[i].ToString());
            }

            return string.Join(", ", elements.ToArray());
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            if (binder.Name == "Length") {
                result = this.Length;
                return true;
            }

            if (binder.Name.Length == 1 && this.m_positions.ContainsKey(binder.Name[0]))
            {
                result = m_values[this.m_positions[binder.Name[0]]];
                return true;
            }

            Dictionary<char, int> positions = new Dictionary<char, int>(binder.Name.Length);
            List<T> values = new List<T>(binder.Name.Length);
            int i = 0;
            foreach (char c in binder.Name)
            {
                if (!this.m_positions.ContainsKey(c))
                    return base.TryGetMember(binder, out result);

                values.Add(m_values[m_positions[c]]);
                positions.Add(c, i);

                i++;
            }

            result = new Vector<T>(positions, values.ToArray());
            return true;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            // sanity checking.
            foreach (char c in binder.Name)
            {
                if (!this.m_positions.ContainsKey(c))
                    return base.TrySetMember(binder, value);
            }

            Vector<T> vectorValue = value as Vector<T>;

            if (vectorValue == null && binder.Name.Length == 1 && value is T)
            {
                m_values[m_positions[binder.Name[0]]] = (T)value;
                return true;
            }
            else if (vectorValue == null)
                throw new ArgumentException("You may only set properties of a Vector to another Vector of the same type.");
            if (vectorValue.Length != binder.Name.Length)
                throw new ArgumentOutOfRangeException("The length of the Vector given does not match the length of the Vector to assign it to.");

            int i = 0;
            foreach (char c in binder.Name)
            {
                m_values[m_positions[c]] = vectorValue[i];
                i++;
            }

            return true;
        }
    }
}
namespace Swizzle
{
/// 
///这实现了问题中描述的Vector4类,基于我们完全通用的
///向量类。
/// 
类向量4:向量
{
公共向量4(int-val0,int-val1,int-val2,int-val3)
:base(新字典{{'t',0},{'x',1},{'y',2},{'z',3},
{'a',0},{'r',1},{'g',2},{'b',3},
新int[]{val0,val1,val2,val3})
{ }
}
班级计划
{
静态void Main(字符串[]参数)
{
动态v1、v2、v3;
v1=新矢量4(1,2,3,4);
v2=v1.rgb;
//打印:v2.r:2
WriteLine(“v2.r:{0}”,v2.r);
//印刷品:红色:2
int red=v2.r;
WriteLine(“红色:{0}”,红色);
//打印:v2有3个元素。
WriteLine(“v2有{0}个元素。”,v2.Length);
v3=新矢量4(5,6,7,8);
v3.ar=v2.gb;//是的,名称被保留!v3=(3,4,7,8)
v2.r=5;
//v2.a=5;//失败:v2没有“a”元素,只有“r”、“g”和“b”
//一些有趣的东西也会起作用
WriteLine(“v3.gr:{0}”,v3.gr);
v3.rg=v3.gr;//切换绿色和红色
WriteLine(“v3.gr:{0}”,v3.gr);
Console.WriteLine(“\r\n按任意键继续”);
Console.ReadKey(true);
}
}
类向量:DynamicObject
{
私有T[]m_值;
私人字典m_位置;
公共向量(字典位置,参数T[]值)
{
此m_位置=位置;
此.m_值=值;
}
公共T此[int索引]{
获取{返回此.m_值[索引];}
}
公共整数长度
{
获取{返回this.m_values.Length;}
}
公共重写字符串ToString()
{
列表元素=新列表(此.Length);
for(int i=0;i
请参见