C++ 电子游戏编程中的数学
我刚刚在大学完成了第二年的游戏课程,这一直困扰着我数学和游戏编程的关系。到目前为止,我一直在游戏中使用C++ 电子游戏编程中的数学,c++,math,video-game-consoles,C++,Math,Video Game Consoles,我刚刚在大学完成了第二年的游戏课程,这一直困扰着我数学和游戏编程的关系。到目前为止,我一直在游戏中使用向量,矩阵,和四元数,我可以理解这些如何适合游戏 这是一个关于数学和实时图形编程之间关系的一般性问题,我很好奇数学的动态性。是否所有公式和导数都是预定义的(半定义的) 实时计算导数/积分是否可行 这些都是我不认为它们如何适合编程/数学的例子 MacLaurin/Talor Series我可以看出这很有用,但是在这种情况下,你必须传递函数及其导数,还是可以传递一个函数,让它为你算出导数 MacLa
向量
,矩阵
,和四元数
,我可以理解这些如何适合游戏
这是一个关于数学和实时图形编程之间关系的一般性问题,我很好奇数学的动态性。是否所有公式和导数都是预定义的(半定义的)
实时计算导数/积分是否可行
这些都是我不认为它们如何适合编程/数学的例子
MacLaurin/Talor Series
我可以看出这很有用,但是在这种情况下,你必须传递函数及其导数,还是可以传递一个函数,让它为你算出导数
MacLaurin(sin(X)); or MacLaurin(sin(x), cos(x), -sin(x));
导数/积分
这与第一点有关。计算在运行时动态完成的函数的y'
,或者这是静态完成的,可能是使用集合函数中的变量
f = derive(x); or f = derivedX;
Bilnear补丁
我们了解到,这是一种可以生成小块景观的方法,可以“缝合”在一起,这在游戏中会发生吗?我从来没有听说过这种方法(尽管我的知识非常有限)被用于程序方法或其他方面。到目前为止,我所做的是处理顶点信息的数组
抱歉,如果这是离题的话,但是这里的社区似乎在这类事情上很到位
谢谢。游戏中的大多数数学都是为了尽可能便宜地计算,交易速度高于准确性。例如,许多数字运算使用整数或单精度浮点,而不是双精度浮点
不确定你的具体例子,但如果你能事先为一个导数定义一个便宜的(计算)公式,那么这比在运动中计算东西要好。在游戏中,性能是最重要的。如果可以静态地进行,你将找不到任何动态地进行的操作,除非它能显著提高视觉保真度。2)导数和积分通常不会在大型数据集上实时计算,其成本太高。相反,它们是预先计算的。例如(在我的头顶)渲染单个散射媒体Bo Sun等人使用他们的“airlight模型”,该模型由许多代数快捷方式组成,以获得预计算的查找表
3) 流式传输大数据集是一个大主题,特别是在地形中
你们在游戏中遇到的很多数学问题都是为了解决非常具体的问题,而且通常都很简单。线性代数的应用远远超过任何微积分。在图形方面(我最喜欢这个),很多算法都来自于学术界的研究,然后游戏程序员为了提高速度对它们进行了修改:尽管现在连学术研究都把提高速度作为他们的目标
我推荐两本书实时碰撞检测和实时渲染,它包含游戏引擎编程中使用的大部分数学和概念的内含。 < P>我认为你对C++语言本身的理解存在一个根本性的问题。C++中的函数与数学函数不一样。所以,在C++中,您可以定义一个函数(我现在称之为避免混淆的方法)来实现数学函数:
float f (float x)
{
return x * x + 4.0f * x + 6.0f; // f(x) = x^2 + 4x + 6
}
class ExampleFunction : Function
{
float f (float x) { return x * x + 4.0f * x + 6.0f; } // f(x) = x^2 + 4x + 6
float df (float x) { return 2.0f * x + 4.0f; } // f'(x) = 2x + 4
float ddf (float x) { return 2.0f; } // f''(x) = 2
};
<>在C++中,除了获得给定x的f(x)值外,没有其他方法可以做任何事情。数学函数f(x)可以很容易地进行变换,例如f’(x),在上面的例子中是f’(x)=2x+4。要在C++中这样做,您需要定义一个方法DF(x):
你不能这样做:
get_derivative (f(x));
并让方法get_导数
为您转换方法f(x)
此外,还必须确保当需要f的导数时,调用方法df。如果你偶然调用g的导数的方法,你的结果会是错误的
然而,对于给定的x,我们可以近似地求出f(x)的导数:
float d (float (*f) (float x), x) // pass a pointer to the method f and the value x
{
const float epsilon = a small value;
float dy = f(x+epsilon/2.0f) - f(x-epsilon/2.0f);
return epsilon / dy;
}
但这是非常不稳定和非常不准确的
现在,在C++中,您可以创建一个类来帮助:
class Function
{
public:
virtual float f (float x) = 0; // f(x)
virtual float df (float x) = 0; // f'(x)
virtual float ddf (float x) = 0; // f''(x)
// if you wanted further transformations you'd need to add methods for them
};
并创建特定的数学函数:
float f (float x)
{
return x * x + 4.0f * x + 6.0f; // f(x) = x^2 + 4x + 6
}
class ExampleFunction : Function
{
float f (float x) { return x * x + 4.0f * x + 6.0f; } // f(x) = x^2 + 4x + 6
float df (float x) { return 2.0f * x + 4.0f; } // f'(x) = 2x + 4
float ddf (float x) { return 2.0f; } // f''(x) = 2
};
并将此类的实例传递给系列扩展例程:
float Series (Function &f, float x)
{
return f.f (x) + f.df (x) + f.ddf (x); // series = f(x) + f'(x) + f''(x)
}
但是,我们仍然需要自己为函数的导数创建一个方法,但至少我们不会意外地调用错误的方法
现在,正如其他人所说,游戏倾向于速度,所以很多数学都被简化了:插值、预计算表等等。您可能对编译时符号微分感兴趣。这(原则上)可以用C++模板来完成。不知道游戏在实践中是否会这样做(对于正确编程来说,符号差异可能过于昂贵,而在编译时使用如此广泛的模板可能过于昂贵,我不知道)
然而,我想你可能会发现这个话题的讨论很有趣。谷歌搜索“c++模板符号导数”会给出一些文章。如果你对符号计算和导数计算感兴趣,有很多很好的答案
然而,作为一种理智的检查,这种符号(分析)演算在游戏环境中实时执行是不实际的
根据我的经验(计算机视觉中的3D几何比游戏更重要),3D几何中的大部分微积分和数学都是通过提前离线计算,然后编码来实现这个数学。很少有人需要在飞行中象征性地计算事物,然后以这种方式获得飞行中的分析公式
任何游戏程序员都能验证吗?Skizz的答案从字面上看是正确的,但仅限于
using namespace std;
template<class Float>
Float f(Float x)
{
return x * x + Float(4.0f) * x + Float(6.0f);
}
struct D
{
D(float x0, float dx0 = 0) : x(x0), dx(dx0) { }
float x, dx;
};
D operator+(const D &a, const D &b)
{
// The rule for the sum of two functions.
return D(a.x+b.x, a.dx+b.dx);
}
D operator*(const D &a, const D &b)
{
// The usual Leibniz product rule.
return D(a.x*b.x, a.x*b.dx+a.dx*b.x);
}
// Here's the function skizz said you couldn't write.
float d(D (*f)(D), float x) {
return f(D(x, 1.0f)).dx;
}
int main()
{
cout << f(0) << endl;
// We can't just take the address of f. We need to say which instance of the
// template we need. In this case, f<D>.
cout << d(&f<D>, 0.0f) << endl;
}