c++ 电子游戏编程中的数学

qqrboqgw  于 2023-08-09  发布在  其他
关注(0)|答案(8)|浏览(95)

我刚刚在大学完成了第二年的游戏课程,这一直困扰着我数学和游戏编程是如何联系在一起的。到目前为止,我一直在游戏中使用VectorsMatricesQuaternions,我可以理解这些如何融入游戏。
这是一个关于数学和真实的图形编程之间关系的General Question,我很好奇数学是如何动态的。是否所有公式和导数都是预定义的(半定义的)?
实时计算导数/积分是否可行?
这些是我不明白的一些东西,它们如何融入编程/数学作为一个例子。

  1. MacLaurin/Talor Series我可以看到这是有用的,但它的情况下,你必须传递你的函数和它的衍生物,或者你可以传递一个单一的函数,并有它的工作,为您的衍生物?
MacLaurin(sin(X)); or MacLaurin(sin(x), cos(x), -sin(x));

字符串

  1. Derivatives /Integrals这与第一点有关。计算函数的y'是在运行时动态完成的,还是静态完成的,也许是在集合函数中使用变量。
f = derive(x); or f = derivedX;

  1. Bilnear Patches我们学习这个方法是为了在小块中生成可以“sewen”在一起的风景,这是游戏中发生的事情吗?我从来没有听说过这个(当然我的知识非常有限)与过程方法或其他方法一起使用。到目前为止,我所做的涉及到处理顶点信息的数组。
    对不起,如果这是题外话,但这里的社区似乎现场,在这类事情。
  • 谢谢-谢谢
3j86kqsm

3j86kqsm1#

Skizz的答案从字面上看是正确的,但只需要一个很小的变化就可以计算C++函数的导数。我们将skizz的函数f修改为

template<class Float> f (Float x)
{
  return x * x + Float(4.0f) * x + Float(6.0f); // f(x) = x^2 + 4x + 6
}

字符串
现在可以编写一个C++函数来计算f对x的导数。这里是一个完整的自包含的程序来计算f的导数。它是精确的(机器精度),因为它没有使用不准确的方法,如有限差分。我在我写的paper中解释了它是如何工作的。它推广到更高的衍生物。请注意,大部分工作是由编译器静态完成的。如果你打开优化,并且你的编译器可以很好地内联,那么它应该和你手工编写的简单函数一样快。有时候更快!特别是,它非常擅长同时计算f和f'的成本,因为它使编译器更容易发现公共子表达式的消除,而不是为f和f'编写单独的函数。

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;
}


它会像您期望的那样打印结果64。尝试其他功能f。一个很好的练习是尝试制定规则,允许减法,除法,三角函数等。

col17t5w

col17t5w2#

2)导数和积分通常不是在大数据集上真实的计算的,其成本太高。相反,它们是预先计算的。例如(在我的头顶)渲染一个单一的散射媒体Bo Sun et al.使用他们的“airlight模型”,其中包括了很多代数捷径,以获得一个预先计算的查找表。
3)流式处理大型数据集是一个很大的主题,特别是在地形中。
你在游戏中遇到的很多数学都是为了解决非常具体的问题,而且通常都很简单。线性代数的应用远远超过任何微积分。在图形学中(我最喜欢这个),很多算法来自学术界的研究,然后游戏程序员为了速度而修改它们:尽管现在学术研究也把速度作为目标。
我推荐这两本书真实的碰撞检测和实时渲染,其中包含了游戏引擎编程中使用的大多数数学和概念。

jvlzgdj9

jvlzgdj93#

我认为你对 C++ 本身的理解有一个根本性的问题。C中的函数与数学函数不同。因此,在C中,你可以定义一个函数(我现在将其称为方法以避免混淆)来实现一个数学函数:

float f (float x)
{
  return x * x + 4.0f * x + 6.0f; // f(x) = x^2 + 4x + 6
}

字符串
在C中,除了对给定的x获取f(x)的值之外,没有办法对方法f做任何事情。数学函数f(x)可以很容易地变换,例如f '(x),在上面的例子中是f'(x)= 2x + 4。要在C中做到这一点,你需要定义一个方法df(x):

float df (float x)
{
  return 2.0f * x + 4.0f; //  f'(x) = 2x + 4
}


你不能这么做

get_derivative (f(x));


然后让方法get_derivative为你转换方法f(x)。
另外,你必须确保当你想要f的导数时,你调用方法df。如果你不小心调用了求g的导数的方法,你的结果就会错。
然而,我们可以近似f(x)对给定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
};


并创建特定的数学函数:

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)
}


但是,我们仍然需要为函数的导数创建一个方法,但至少我们不会意外地调用错误的方法。
现在,正如其他人所说,游戏倾向于速度,所以很多数学都被简化了:插值、预先计算的表等。

2eafrhcq

2eafrhcq4#

游戏中的大多数数学都是为了尽可能便宜地计算,交易速度超过准确性。例如,许多数字运算使用整数或单精度浮点数,而不是双精度浮点数。
不确定你的具体例子,但如果你能预先定义一个便宜的(计算)导数公式,那么这比动态计算要好。

qvk1mo1f

qvk1mo1f5#

在游戏中,性能至关重要。你不会发现任何可以静态完成的事情是动态完成的,除非它导致视觉保真度的显著增加。

yrefmtwq

yrefmtwq6#

您可能对编译时符号微分感兴趣。这可以(原则上)用c模板来完成。不知道游戏是否在实践中做到了这一点(符号区分可能太昂贵了,无法正确编程,而且如此广泛的模板使用可能在编译时太昂贵了,我不知道)。
但是,我想你可能会发现这个主题的讨论很有趣。google“c
模板符号派生”给出的几篇文章。

iqjalb3h

iqjalb3h7#

如果你对符号计算和导数计算感兴趣,有很多很好的答案。
然而,就像一个健全的检查,这种符号(分析)演算是不实际的,在游戏的上下文中做实时。
根据我的经验(计算机视觉中的3D几何比游戏更多),3D几何中的大多数微积分和数学都是通过提前离线计算然后编码来实现这个数学的。你很少需要在运行中进行符号计算,然后通过这种方式得到运行中的分析公式。
有游戏程序员可以验证吗?

bpzcxfmw

bpzcxfmw8#

1)、2)
MacLaurin/Taylor级数(1)在任何情况下都是由导数(2)构造的。
是的,您不太可能需要在运行时象征性地计算这些值中的任何一个--但是可以肯定的是,如果您需要的话,user207442的答案是很好的。
你会发现你需要执行一个数学计算,而且你需要在合理的时间内完成,有时甚至非常快。要做到这一点,即使你重复使用别人的解决方案,你也需要了解基本的分析。
如果你必须自己解决这个问题,好处是你通常只需要一个近似的答案。这意味着,例如,级数类型的展开可以很好地允许您将复杂的函数简化为简单的线性或二次函数,这将非常快。
对于积分,你通常可以用数值计算结果,但它总是比解析解慢得多。区别很可能是实用与否的区别。
简而言之:是的,你需要学习数学,但为了编写程序,而不是让程序为你做。

相关问题