genesis-3d_engine/Engine/foundation/debug/debugfloat.h

377 lines
11 KiB
C
Raw Permalink Normal View History

/****************************************************************************
Copyright (c) 2009, Radon Labs GmbH
Copyright (c) 2011-2013,WebJet Business Division,CYOU
http://www.genesis-3d.com.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
//------------------------------------------------------------------------------
/**
@class Debug::DebugFloat
This class is supposed to make it easier, to restore the exact value of floating-
point-based types, like vector, matrix44, float etc. for debugging.
printf cuts values and rounds it. Also denormalized values might be printed as "0.0".
Its particulary useful, if a certain set of input-parameters lets a function crash.
Just call printHex for floating-point-based params so they are being printed to stdout
with its exact bit-pattern.
That dump can be passed to restoreHex and you can debug that function with that particular
input-set.
Printing a float4 to stdout works like this:
float4 v(1.0f, 2.0f, 3.0f, 4.0f);
DebugFloat::printHex(v, "v");
The output in stdout is this:
v: 0x3F800000, 0x40000000, 0x40400000, 0x40800000
To restore the values, just pass the output to restoreHex
float4 v = DebugFloat::restoreHex(0x3F800000, 0x40000000, 0x40400000, 0x40800000);
Now v has the exact same value(bit pattern) as it had when being printed with printHex
There is also a normal "print" for each type. Quite useful is the quaternion-version, since
it gives a more human-readable output than just the normal debugger.
*/
#include "math/float4.h"
#include "math/matrix44.h"
#include "math/quaternion.h"
#include "math/plane.h"
#include "math/scalar.h"
#include "core/types.h"
#include "util/typepunning.h"
//------------------------------------------------------------------------------
namespace Debug
{
class DebugFloat
{
public:
/// print float's bit pattern as hex to stdout
static void printHex(float val, const char *msg = NULL);
/// print float4's bit pattern as hex to stdout
static void printHex(const Math::float4 &v, const char *msg = NULL);
/// print matrix's bit pattern as hex to stdout
static void printHex(const Math::matrix44 &m, const char *msg = NULL);
/// print quaternion's bit pattern as hex to stdout
static void printHex(const Math::quaternion &q, const char *msg = NULL);
/// print plane's bit pattern as hex to stdout
static void printHex(const Math::plane &p, const char *msg = NULL);
// restore a float's bit pattern
static void restoreHex(float &v, int val);
// restore a float4's bit pattern
static void restoreHex(Math::float4 &v, int x, int y, int z, int w);
// restore a matrix's bit pattern
static void restoreHex(Math::matrix44 &m,
int m0, int m1, int m2, int m3,
int m4, int m5, int m6, int m7,
int m8, int m9, int m10, int m11,
int m12, int m13, int m14, int m15);
// restore a quaternion's bit pattern
static void restoreHex(Math::quaternion &q, int x, int y, int z, int w);
// restore a plane's bit pattern
static void restoreHex(Math::plane &p, int x, int y, int z, int w);
/// print float's values plain to stdout
static void print(const float &v, const char *msg = NULL);
/// print float4's values plain to stdout
static void print(const Math::float4 &v, const char *msg = NULL);
/// print matrix's values plain to stdout
static void print(const Math::matrix44 &m, const char *msg = NULL);
/// print quaternion's values plain to stdout
static void print(const Math::quaternion &q, const char *msg = NULL);
/// print plane's values plain to stdout
static void print(const Math::plane &p, const char *msg = NULL);
};
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::restoreHex(float &v, int val)
{
v = Util::TypePunning<float, int>(val);
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::restoreHex(Math::float4 &v, int x, int y, int z, int w)
{
const int vRaw[4] = {x, y, z, w};
float *p = (float*)&v;
for(int index = 0; index < 4; ++index)
{
*p++ = Util::TypePunning<float, int>(vRaw[index]);
}
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::restoreHex(Math::matrix44 &m,
int m0, int m1, int m2, int m3,
int m4, int m5, int m6, int m7,
int m8, int m9, int m10, int m11,
int m12, int m13, int m14, int m15)
{
const int mRaw[4][4] = {{m0, m1, m2, m3},
{m4, m5, m6, m7},
{m8, m9, m10, m11},
{m12, m13, m14, m15}};
float *p = (float*)&m.getrow0();
for(int index = 0; index < 16; ++index)
{
*p++ = Util::TypePunning<float, int>(mRaw[index/4][index%4]);
}
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::restoreHex(Math::quaternion &q, int x, int y, int z, int w)
{
const int vRaw[4] = {x, y, z, w};
float *p = (float*)&q;
for(int index = 0; index < 4; ++index)
{
*p++ = Util::TypePunning<float, int>(vRaw[index]);
}
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::restoreHex(Math::plane &pl, int x, int y, int z, int w)
{
const int vRaw[4] = {x, y, z, w};
float *p = (float*)&pl;
for(int index = 0; index < 4; ++index)
{
*p++ = Util::TypePunning<float, int>(vRaw[index]);
}
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::printHex(const Math::matrix44 &m, const char *msg)
{
if(msg) n_printf("%s: ", msg);
printHex(m.getrow0());
n_printf(", ");
printHex(m.getrow1());
n_printf(", ");
printHex(m.getrow2());
n_printf(", ");
printHex(m.getrow3());
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::printHex(const Math::float4 &v, const char *msg)
{
if(msg) n_printf("%s: ", msg);
const float *p = (const float*)&v;
printHex(p[0]);
n_printf(", ");
printHex(p[1]);
n_printf(", ");
printHex(p[2]);
n_printf(", ");
printHex(p[3]);
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::printHex(const Math::quaternion &q, const char *msg)
{
if(msg) n_printf("%s: ", msg);
const float *p = (const float*)&q;
printHex(p[0]);
n_printf(", ");
printHex(p[1]);
n_printf(", ");
printHex(p[2]);
n_printf(", ");
printHex(p[3]);
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::printHex(const Math::plane &pl, const char *msg)
{
if(msg) n_printf("%s: ", msg);
const float *p = (const float*)&pl;
printHex(p[0]);
n_printf(", ");
printHex(p[1]);
n_printf(", ");
printHex(p[2]);
n_printf(", ");
printHex(p[3]);
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::printHex(float val, const char *msg)
{
if(msg) n_printf("%s: ", msg);
const int bits = Util::TypePunning<int, float>(val);
unsigned char tmp;
char buffer[(sizeof(int)*2)+3];
char *p = buffer;
*p++ = '0';
*p++ = 'x';
for( int i = sizeof(int)*2-1; i > -1; --i )
{
tmp = ( bits >> (i*4) ) & 0xF;
if( tmp >= 10 )
{
*p++ = tmp - 10 + 'A';
}
else
{
*p++ = tmp + '0';
}
}
*p = '\0';
n_printf("%s", buffer );
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::print(const Math::float4 &v, const char *msg)
{
if(msg) n_printf("%s: ", msg);
n_printf("%10.4f %10.4f %10.4f %10.4f", v.x(), v.y(), v.z(), v.w());
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::print(const float &v, const char *msg)
{
if(msg) n_printf("%s:\n", msg);
n_printf("%10.4f", v);
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::print(const Math::matrix44 &m, const char *msg)
{
if(msg) n_printf("%s:\n", msg);
// yes, looks weird, rows and cols seem to be mixed, but its not
print(Math::float4(m.getrow0().x(), m.getrow1().x(), m.getrow2().x(), m.getrow3().x()), NULL);
n_printf("\n");
print(Math::float4(m.getrow0().y(), m.getrow1().y(), m.getrow2().y(), m.getrow3().y()), NULL);
n_printf("\n");
print(Math::float4(m.getrow0().z(), m.getrow1().z(), m.getrow2().z(), m.getrow3().z()), NULL);
n_printf("\n");
print(Math::float4(m.getrow0().w(), m.getrow1().w(), m.getrow2().w(), m.getrow3().w()), NULL);
n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::print(const Math::quaternion &q, const char *msg)
{
if(msg) n_printf("%s:\n", msg);
if(Math::n_nearequal(q.length(), 1.0f, 0.00001f))
{
const Math::scalar angle = Math::n_acos(q.w()) * 2.0f;
n_printf(" axis : %f %f %f\n"
" w : %f\n"
" magnitude: %f rad: %f deg: %f\n",
q.x(), q.y(), q.z(), q.w(), q.length(), angle, Math::n_rad2deg(angle));
}
else
{
n_printf(" axis : %f %f %f\n"
" w : %f\n"
" magnitude: %f\n",
q.x(), q.y(), q.z(), q.w(), q.length());
}
if(msg) n_printf("\n");
}
//------------------------------------------------------------------------------
/**
*/
inline
void
DebugFloat::print(const Math::plane &p, const char *msg)
{
if(msg) n_printf("%s: ", msg);
print(Math::float4(p.a(), p.b(), p.c(), p.d()), NULL);
if(msg) n_printf("\n");
}
} // namespace Debug
//------------------------------------------------------------------------------