Ogre不负责任研究(三)Math基础类初探

3 Math基础类初探

概览,Math基础类封装了常用的数学公式,特别的,提供了对角度和弧度的支持。该函数封装了一些使用汇编语言实现的基础数学类,因此效率还是有保证的。汇编的函数在asm_math.h头文件中被定义,不过汇编那个对俺还是太高深了暂时放弃……。

3.1几个公有静态变量的定义技巧:

const Real Math::POS_INFINITY = std::numeric_limits<Real>::infinity();

const Real Math::NEG_INFINITY = -std::numeric_limits<Real>::infinity();

const Real Math::PI = Real( 4.0 * atan( 1.0 ) );

const Real Math::TWO_PI = Real( 2.0 * PI );

const Real Math::HALF_PI = Real( 0.5 * PI );

const Real Math::fDeg2Rad = PI / Real(180.0);

const Real Math::fRad2Deg = Real(180.0) / PI;

这些变量分别是正无穷,负无穷,派,2派,二分之一派,角度到弧度的变换常数,弧度到角度的变换常数。首先是前两个,在std里定义的实数的上限,注意,这个Real型是在OgrePrerequisites.h中定义的,他可能是double也可能是单精度浮点数。但是通常来讲是一个单精度浮点数。

 

std::numeric_limits<Real>::infinity()返回预定义“正无穷大”,无穷大和std::numeric_limits<Real>::max()的定义是有区别的,max仅仅是T类型能表示的最大的数而已,顺便说一下numeric_limits这个模板类还提供了以下一些东东:【摘自CSDN】。不过里面常用的东西貌似并不多……。知道有这么个东西就行了,需要的时候现查也来得及。需要注意的是,std::numeric_limits<float>::max()返回的其实是一个整数,这是为啥呢?意思是,返回的数是float能表示的精度最大的“最小的正数”,如果你真的需要一个最小的float数,使用

- std::numeric_limits<float>::max()即可。

 

digits10

返回目标类型在十进制下可以表示的最大位数

epsilon

返回目标数据类型能表示的最逼近1的正数和1的差的绝对值

has_denorm

测试目标类型是不是可以非规范化表示示

has_denorm_loss

测试所有类型是不是能测出因为非规范化而造成的精度损失(不是因为结果本身的不精确)

has_infinity

测试目标类型是不是能表示无限(比如被0除,或者其他一些情况)

has_quiet_NaN

检查目标类型是不是支持安静类型的NaN

has_signaling_NaN

检查目标类型是不是支持信号类型的NaN

infinity

检查目标类型的无限类型(如果支持无限表示)

is_bounded

检查目标类型的取值是否有限

is_exact

测试目标类型的计算结果是不是不会造成舍入误差(比如float0

is_iec559

测试目标类型是不是符合IEC559标准

is_integer

测试目标类型是不是可以用整型来表示(比如char1float0

is_modulo

测试目标类型是否可以用模来表示。

is_signed

测试目标类型是否是带符号的

is_specialized

max

测试目标类型是不是在numeric_limits .模板类中有特殊定义

返回可取的有限最大值

max_exponent

Returns the maximum positive integral exponent that the floating-point type can represent as a finite value when a base of radix is raised to that power.

max_exponent10

Returns the maximum positive integral exponent that the floating-point type can represent as a finite value when a base of ten is raised to that power.

min

返回可取的最小值(规范化)

min_exponent

Returns the maximum negative integral exponent that the floating-point type can represent as a finite value when a base of radix is raised to that power.

min_exponent10

Returns the maximum negative integral exponent that the floating-point type can represent as a finite value when a base of ten is raised to that power.

quiet_NaN

返回目标类型的安静NAN的表示

radix

Returns the integral base, referred to as radix, used for the representation of a type.

round_error

返回目标类型的最大可能的舍入误差

round_style

返回一个值,描述不同的方法,其实现可以将浮点数舍入成整数。

signaling_NaN

返回目标类型关于信号NAN的表示

tinyness_before

测试目标类型是不是能测定出微小的舍入误差

traps

Tests whether trapping that reports on arithmetic exceptions is implemented for a type.

 

3.2 sinTabletanTable

这里是一个空间换时间的技巧——使用三角函数表的方式实现快速求SinTan。既然做源码分析,那么就要学习高手们的技巧~

原理是这样子的,以sin为例,首先定义一个静态的sin表,之所以设置成静态,是为了节省空间!

 

头文件:static Real* mSinTable;

CPP初始化:Real *Math::mSinTable = NULL;

 

在构造Math类的时候,需要传入一个刻度表的容量trigTableSize,也就是三角函数表的容量,这个数越大,刻度越细,求出来的sin值越精确,但是消耗的空间也就越大,反之类推,亦然。然后根据这个trigTableSize计算每一个三角函数表的跨度。mTrigTableFactor随后为Real* mSinTable分配空间。

 

mSinTable = OGRE_ALLOC_T(Real, mTrigTableSize, MEMCATEGORY_GENERAL);

 

这个OGRE_ALLOC_T看起来很恐怖,封装了好几层,追溯了半天也没追出来,不过简单的说就是一个线程安全的内存分配函数,这个以后还得再研究研究,不过今天的重点不是他。

 

分配好空间之后,就要计算这个三角函数表了。方法为

    void Math::buildTrigTables(void)

    {

        // Build trig lookup tables

        // Could get away with building only PI sized Sin table but simpler this

        // way. Who cares, it'll ony use an extra 8k of memory anyway and I like

        // simplicity.

        Real angle;

        for (int i = 0; i < mTrigTableSize; ++i)

        {

            angle = Math::TWO_PI * i / mTrigTableSize;

            mSinTable[i] = sin(angle);

            mTanTable[i] = tan(angle);

        }

    }

这个方法定义了一个2PI容量的正弦三角函数表,据大牛说是为了方便起见,为了节省空间也可以只定义一个PI容量的三角函数表,不过查起表来就比较麻烦了。

 

其他一些东西,还有包括常用三角函数,求指数,求平方根,求平方根倒数,求点是否在三角形内,求线面是否相交,球体和面,立方体是否相交等等很多和查询有关的数学基础函数。常用函数举例:如Sign方法,求一个浮点数的符号。如果大于0.0,返回1.0,小于0.0,返回-1.0

 

这个类其实已经很底层了,不过分析Ogre源码的第一步是分析其架构,所以算法的分析和研究放到以后再头疼吧。

你可能感兴趣的:(Ogre不负责任研究(三)Math基础类初探)