Merge from 1.7 branch, revisions 3877-3908. Fix for getSphericalCoordinateAngles, some warnign fixes, md2 normal fix, several GUI fixes, isPointInside fix, zip endianess fix.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3909 dfc29bdd-3216-0410-991c-e03cc46cb475master
parent
5d7b7931e6
commit
afa978f2a5
10
changes.txt
10
changes.txt
|
@ -289,6 +289,16 @@ The following names can be queried for the given types:
|
|||
-----------------------------
|
||||
Changes in 1.7.3 (??.??.2011)
|
||||
|
||||
- editbox no longer moves text into next line when it fails wrapping creating senseless empty lines which mess up scrolling.
|
||||
|
||||
- Fix crash in editbox when scrolling up with empty first lines caused by textwrapping.
|
||||
|
||||
- triangle3d::isPointInside can now work with larger integers, old version failed already with values in the 3-digit range. It got also faster. (thx @ Eigen for report + testcase and REDDemon for patch proposal).
|
||||
|
||||
- Fix focus problem when removing an unfocused modal dialog reported by Reiko here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44358
|
||||
|
||||
- Add integer template specialization for vector3d::getSphericalCoordinateAngles which rounds angles to nearest integer now.
|
||||
|
||||
- Recalculate FrameRect and ScrollPos in CGUIEditBox when AbsoluteRect gets changed (thx @ serengeor for report + testcase)
|
||||
|
||||
- Fix 'k' in bigfont.png (thx @ Scrappi for reporting)
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace scene
|
|||
//! Transparent effect scene nodes, drawn after Transparent nodes. They are sorted from back to front and drawn in that order.
|
||||
ESNRP_TRANSPARENT_EFFECT =32,
|
||||
|
||||
//! Drawn after the transparent nodes, the time for drawing shadow volumes
|
||||
//! Drawn after the solid nodes, before the transparent nodes, the time for drawing shadow volumes
|
||||
ESNRP_SHADOW =64
|
||||
};
|
||||
|
||||
|
|
|
@ -81,21 +81,39 @@ namespace core
|
|||
return d2 < d3 ? rbc : rca;
|
||||
}
|
||||
|
||||
//! Check if a point is inside the triangle
|
||||
//! Check if a point is inside the triangle (border-points count also as inside)
|
||||
/** \param p Point to test. Assumes that this point is already
|
||||
on the plane of the triangle.
|
||||
\return True if the point is inside the triangle, otherwise false. */
|
||||
bool isPointInside(const vector3d<T>& p) const
|
||||
{
|
||||
return (isOnSameSide(p, pointA, pointB, pointC) &&
|
||||
isOnSameSide(p, pointB, pointA, pointC) &&
|
||||
isOnSameSide(p, pointC, pointA, pointB));
|
||||
const vector3d<T> a = pointC - pointA;
|
||||
const vector3d<T> b = pointB - pointA;
|
||||
const vector3d<T> c = p - pointA;
|
||||
|
||||
const f64 dotAA = a.dotProduct( a);
|
||||
const f64 dotAB = a.dotProduct( b);
|
||||
const f64 dotAC = a.dotProduct( c);
|
||||
const f64 dotBB = b.dotProduct( b);
|
||||
const f64 dotBC = b.dotProduct( c);
|
||||
|
||||
// get coordinates in barycentric coordinate system
|
||||
const f64 invDenom = 1/(dotAA * dotBB - dotAB * dotAB);
|
||||
const f64 u = (dotBB * dotAC - dotAB * dotBC) * invDenom;
|
||||
const f64 v = (dotAA * dotBC - dotAB * dotAC ) * invDenom;
|
||||
|
||||
// We count border-points as inside to keep downward compatibility.
|
||||
// That's why we use >= and <= instead of > and < as more commonly seen on the web.
|
||||
return (u >= 0) && (v >= 0) && (u + v <= 1);
|
||||
}
|
||||
|
||||
//! Check if a point is inside the triangle.
|
||||
/** This method is an implementation of the example used in a
|
||||
paper by Kasper Fauerby original written by Keidy from
|
||||
Mr-Gamemaker.
|
||||
This was once faster than an old isPointInside implementation, but the
|
||||
current isPointInside is usualy as fast, sometimes even faster.
|
||||
Border-points in isPointInsideFast are not defined, some are inside and some outside.
|
||||
\param p Point to test. Assumes that this point is already
|
||||
on the plane of the triangle.
|
||||
\return True if point is inside the triangle, otherwise false. */
|
||||
|
|
|
@ -246,7 +246,7 @@ public:
|
|||
if (tmp < 0.0)
|
||||
tmp = -tmp;
|
||||
if ( tmp > 1.0 ) // avoid floating-point trouble
|
||||
tmp = 1.0;
|
||||
tmp = 1.0;
|
||||
|
||||
return atan(sqrt(1 - tmp*tmp) / tmp) * RADTODEG64;
|
||||
}
|
||||
|
|
|
@ -421,6 +421,26 @@ namespace core
|
|||
template <>
|
||||
inline vector3d<s32>& vector3d<s32>::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;}
|
||||
|
||||
template <>
|
||||
inline vector3d<s32> vector3d<s32>::getSphericalCoordinateAngles()
|
||||
{
|
||||
vector3d<s32> angle;
|
||||
const f64 length = X*X + Y*Y + Z*Z;
|
||||
|
||||
if (length)
|
||||
{
|
||||
if (X!=0)
|
||||
{
|
||||
angle.Y = round32((f32)(atan2((f64)Z,(f64)X) * RADTODEG64));
|
||||
}
|
||||
else if (Z<0)
|
||||
angle.Y=180;
|
||||
|
||||
angle.X = round32((f32)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64));
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
//! Typedef for a f32 3d vector.
|
||||
typedef vector3d<f32> vector3df;
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace scene
|
|||
{
|
||||
|
||||
const s32 MD2_FRAME_SHIFT = 2;
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / ( 1 << MD2_FRAME_SHIFT );
|
||||
|
||||
const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
|
||||
|
||||
const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
|
||||
|
||||
|
@ -194,27 +193,27 @@ struct SMD2AnimationType
|
|||
|
||||
static const SMD2AnimationType MD2AnimationTypeList[21] =
|
||||
{
|
||||
{ 0, 39, 9 }, // STAND
|
||||
{ 40, 45, 10 }, // RUN
|
||||
{ 46, 53, 10 }, // ATTACK
|
||||
{ 54, 57, 7 }, // PAIN_A
|
||||
{ 58, 61, 7 }, // PAIN_B
|
||||
{ 62, 65, 7 }, // PAIN_C
|
||||
{ 66, 71, 7 }, // JUMP
|
||||
{ 72, 83, 7 }, // FLIP
|
||||
{ 84, 94, 7 }, // SALUTE
|
||||
{ 95, 111, 10 }, // FALLBACK
|
||||
{ 112, 122, 7 }, // WAVE
|
||||
{ 123, 134, 6 }, // POINT
|
||||
{ 135, 153, 10 }, // CROUCH_STAND
|
||||
{ 154, 159, 7 }, // CROUCH_WALK
|
||||
{ 160, 168, 10 }, // CROUCH_ATTACK
|
||||
{ 169, 172, 7 }, // CROUCH_PAIN
|
||||
{ 173, 177, 5 }, // CROUCH_DEATH
|
||||
{ 178, 183, 7 }, // DEATH_FALLBACK
|
||||
{ 184, 189, 7 }, // DEATH_FALLFORWARD
|
||||
{ 190, 197, 7 }, // DEATH_FALLBACKSLOW
|
||||
{ 198, 198, 5 }, // BOOM
|
||||
{ 0, 39, 9}, // STAND
|
||||
{ 40, 45, 10}, // RUN
|
||||
{ 46, 53, 10}, // ATTACK
|
||||
{ 54, 57, 7}, // PAIN_A
|
||||
{ 58, 61, 7}, // PAIN_B
|
||||
{ 62, 65, 7}, // PAIN_C
|
||||
{ 66, 71, 7}, // JUMP
|
||||
{ 72, 83, 7}, // FLIP
|
||||
{ 84, 94, 7}, // SALUTE
|
||||
{ 95, 111, 10}, // FALLBACK
|
||||
{112, 122, 7}, // WAVE
|
||||
{123, 134, 6}, // POINT
|
||||
{135, 153, 10}, // CROUCH_STAND
|
||||
{154, 159, 7}, // CROUCH_WALK
|
||||
{160, 168, 10}, // CROUCH_ATTACK
|
||||
{169, 172, 7}, // CROUCH_PAIN
|
||||
{173, 177, 5}, // CROUCH_DEATH
|
||||
{178, 183, 7}, // DEATH_FALLBACK
|
||||
{184, 189, 7}, // DEATH_FALLFORWARD
|
||||
{190, 197, 7}, // DEATH_FALLBACKSLOW
|
||||
{198, 198, 5}, // BOOM
|
||||
};
|
||||
|
||||
|
||||
|
@ -238,6 +237,7 @@ CAnimatedMeshMD2::~CAnimatedMeshMD2()
|
|||
InterpolationBuffer->drop();
|
||||
}
|
||||
|
||||
|
||||
//! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
|
||||
u32 CAnimatedMeshMD2::getFrameCount() const
|
||||
{
|
||||
|
@ -294,7 +294,6 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
{
|
||||
u32 firstFrame, secondFrame;
|
||||
f32 div;
|
||||
core::vector3df* NormalTable = (core::vector3df*)&Q2_VERTEX_NORMAL_TABLE;
|
||||
|
||||
// TA: resolve missing ipol in loop between end-start
|
||||
|
||||
|
@ -311,10 +310,10 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
|
||||
|
||||
firstFrame = frame >> MD2_FRAME_SHIFT;
|
||||
secondFrame = core::if_c_a_else_b ( firstFrame + 1 > e, s, firstFrame + 1 );
|
||||
secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
|
||||
|
||||
firstFrame = core::s32_min ( FrameCount - 1, firstFrame );
|
||||
secondFrame = core::s32_min ( FrameCount - 1, secondFrame );
|
||||
firstFrame = core::s32_min(FrameCount - 1, firstFrame);
|
||||
secondFrame = core::s32_min(FrameCount - 1, secondFrame);
|
||||
|
||||
//div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
|
||||
frame &= (1<<MD2_FRAME_SHIFT) - 1;
|
||||
|
@ -322,24 +321,29 @@ void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop,
|
|||
}
|
||||
|
||||
video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
SMD2Vert* first = FrameList[firstFrame].pointer();
|
||||
SMD2Vert* second = FrameList[secondFrame].pointer();
|
||||
|
||||
// interpolate both frames
|
||||
const u32 count = FrameList[firstFrame].size();
|
||||
for (u32 i=0; i<count; ++i)
|
||||
{
|
||||
core::vector3df one, two;
|
||||
one.X = f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X;
|
||||
one.Y = f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y;
|
||||
one.Z = f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z;
|
||||
two.X = f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X;
|
||||
two.Y = f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y;
|
||||
two.Z = f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z;
|
||||
target->Pos = (two - one) * div + one;
|
||||
|
||||
target->Normal = (NormalTable[second->NormalIdx] - NormalTable[first->NormalIdx]) * div
|
||||
+ NormalTable[first->NormalIdx];
|
||||
const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
|
||||
f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
|
||||
f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
|
||||
const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
|
||||
f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
|
||||
f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
|
||||
target->Pos = two.getInterpolated(one, div);
|
||||
const core::vector3df n1(
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
|
||||
const core::vector3df n2(
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
|
||||
Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
|
||||
target->Normal = n2.getInterpolated(n1, div);
|
||||
++target;
|
||||
++first;
|
||||
++second;
|
||||
|
@ -381,7 +385,7 @@ const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
|
|||
|
||||
|
||||
//! set user axis aligned bounding box
|
||||
void CAnimatedMeshMD2::setBoundingBox( const core::aabbox3df& box)
|
||||
void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
|
||||
{
|
||||
InterpolationBuffer->BoundingBox = box;
|
||||
}
|
||||
|
@ -396,7 +400,7 @@ E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
|
|||
|
||||
//! Returns frame loop data for a special MD2 animation type.
|
||||
void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
s32& outBegin, s32& outEnd, s32& outFPS) const
|
||||
{
|
||||
if (l < 0 || l >= EMAT_COUNT)
|
||||
return;
|
||||
|
@ -405,7 +409,7 @@ void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
|
|||
outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
|
||||
|
||||
// correct to anim between last->first frame
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : ( 1 << MD2_FRAME_SHIFT ) - 1;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
|
||||
}
|
||||
|
||||
|
@ -420,7 +424,7 @@ bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
|
|||
{
|
||||
outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
|
||||
outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : ( 1 << MD2_FRAME_SHIFT ) - 1;
|
||||
outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
|
||||
outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -520,7 +520,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
|||
{
|
||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||
if ((s32)BrokenText[lineNo-1].size() < cp)
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1;
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + core::max_((u32)1, BrokenText[lineNo-1].size())-1;
|
||||
else
|
||||
CursorPos = BrokenTextPositions[lineNo-1] + cp;
|
||||
}
|
||||
|
@ -551,7 +551,7 @@ bool CGUIEditBox::processKey(const SEvent& event)
|
|||
{
|
||||
s32 cp = CursorPos - BrokenTextPositions[lineNo];
|
||||
if ((s32)BrokenText[lineNo+1].size() < cp)
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1;
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + core::max_((u32)1, BrokenText[lineNo+1].size())-1;
|
||||
else
|
||||
CursorPos = BrokenTextPositions[lineNo+1] + cp;
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ void CGUIEditBox::breakText()
|
|||
s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
|
||||
s32 worldlgth = font->getDimension(word.c_str()).Width;
|
||||
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth)
|
||||
if (WordWrap && length + worldlgth + whitelgth > elWidth && line.size() > 0)
|
||||
{
|
||||
// break to next line
|
||||
length = worldlgth;
|
||||
|
|
|
@ -33,7 +33,7 @@ bool CGUIModalScreen::canTakeFocus(IGUIElement* target) const
|
|||
{
|
||||
return (target && ((const IGUIElement*)target == this // this element can take it
|
||||
|| isMyChild(target) // own children also
|
||||
|| (target->getType() == EGUIET_MODAL_SCREEN )// other modals also fine
|
||||
|| (target->getType() == EGUIET_MODAL_SCREEN ) // other modals also fine (is now on top or explicitely requested)
|
||||
|| (target->getParent() && target->getParent()->getType() == EGUIET_MODAL_SCREEN ))) // children of other modals will do
|
||||
;
|
||||
}
|
||||
|
@ -86,6 +86,13 @@ bool CGUIModalScreen::OnEvent(const SEvent& event)
|
|||
switch(event.GUIEvent.EventType)
|
||||
{
|
||||
case EGET_ELEMENT_FOCUSED:
|
||||
if ( event.GUIEvent.Caller == this && isMyChild(event.GUIEvent.Element) )
|
||||
{
|
||||
Environment->removeFocus(0); // can't setFocus otherwise at it still has focus here
|
||||
Environment->setFocus(event.GUIEvent.Element);
|
||||
MouseDownTime = os::Timer::getTime();
|
||||
return true;
|
||||
}
|
||||
if ( !canTakeFocus(event.GUIEvent.Caller))
|
||||
{
|
||||
if ( !Children.empty() )
|
||||
|
|
|
@ -104,7 +104,7 @@ IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreC
|
|||
file->read(&sig, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(sig);
|
||||
sig = os::Byteswap::byteswap(sig);
|
||||
#endif
|
||||
|
||||
file->seek(0);
|
||||
|
@ -126,7 +126,7 @@ bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const
|
|||
|
||||
file->read( &header.Sig, 4 );
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(header.Sig);
|
||||
header.Sig = os::Byteswap::byteswap(header.Sig);
|
||||
#endif
|
||||
|
||||
return header.Sig == 0x04034b50 || // ZIP
|
||||
|
@ -192,8 +192,8 @@ bool CZipReader::scanGZipHeader()
|
|||
{
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(header.sig);
|
||||
os::Byteswap::byteswap(header.time);
|
||||
header.sig = os::Byteswap::byteswap(header.sig);
|
||||
header.time = os::Byteswap::byteswap(header.time);
|
||||
#endif
|
||||
|
||||
// check header value
|
||||
|
@ -209,7 +209,7 @@ bool CZipReader::scanGZipHeader()
|
|||
File->read(&dataLen, 2);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(dataLen);
|
||||
dataLen = os::Byteswap::byteswap(dataLen);
|
||||
#endif
|
||||
|
||||
// skip it
|
||||
|
@ -274,8 +274,8 @@ bool CZipReader::scanGZipHeader()
|
|||
File->read(&entry.header.DataDescriptor.UncompressedSize, 4);
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32);
|
||||
os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize);
|
||||
entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32);
|
||||
entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize);
|
||||
#endif
|
||||
|
||||
// now we've filled all the fields, this is just a standard deflate block
|
||||
|
|
|
@ -5,49 +5,43 @@
|
|||
|
||||
using namespace irr;
|
||||
using namespace core;
|
||||
using namespace scene;
|
||||
using namespace video;
|
||||
using namespace io;
|
||||
using namespace gui;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Tests MD2 animations.
|
||||
/** At the moment, this just verifies that the last frame of the animation produces the expected bitmap. */
|
||||
bool md2Animation(void)
|
||||
bool testLastFrame()
|
||||
{
|
||||
// Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions.
|
||||
IrrlichtDevice *device = createDevice( EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
assert(device);
|
||||
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
IVideoDriver* driver = device->getVideoDriver();
|
||||
ISceneManager * smgr = device->getSceneManager();
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager * smgr = device->getSceneManager();
|
||||
|
||||
IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
IAnimatedMeshSceneNode* node;
|
||||
assert(mesh);
|
||||
scene::IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
|
||||
bool result = (mesh != 0);
|
||||
if(mesh)
|
||||
if (mesh)
|
||||
{
|
||||
node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
assert(node);
|
||||
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
|
||||
if(node)
|
||||
if (node)
|
||||
{
|
||||
node->setPosition(vector3df(20, 0, 30));
|
||||
node->setMaterialFlag(EMF_LIGHTING, false);
|
||||
node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
node->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp"));
|
||||
node->setLoopMode(false);
|
||||
|
||||
(void)smgr->addCameraSceneNode();
|
||||
|
||||
// Just jump to the last frame since that's all we're interested in.
|
||||
node->setMD2Animation(EMAT_DEATH_FALLBACK);
|
||||
node->setMD2Animation(scene::EMAT_DEATH_FALLBACK);
|
||||
node->setCurrentFrame((f32)(node->getEndFrame()));
|
||||
node->setAnimationSpeed(0);
|
||||
device->run();
|
||||
driver->beginScene(true, true, SColor(255, 255, 255, 0));
|
||||
driver->beginScene(true, true, video::SColor(255, 255, 255, 0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
if (mesh->getBoundingBox() != mesh->getMesh(node->getEndFrame())->getBoundingBox())
|
||||
|
@ -79,3 +73,56 @@ bool md2Animation(void)
|
|||
return result;
|
||||
}
|
||||
|
||||
// Tests MD2 normals.
|
||||
bool testNormals()
|
||||
{
|
||||
// Use EDT_BURNINGSVIDEO since it is not dependent on (e.g.) OpenGL driver versions.
|
||||
IrrlichtDevice *device = createDevice(video::EDT_BURNINGSVIDEO, dimension2d<u32>(160, 120), 32);
|
||||
if (!device)
|
||||
return false;
|
||||
|
||||
video::IVideoDriver* driver = device->getVideoDriver();
|
||||
scene::ISceneManager * smgr = device->getSceneManager();
|
||||
|
||||
scene::IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
|
||||
|
||||
bool result = (mesh != 0);
|
||||
if (mesh)
|
||||
{
|
||||
scene::IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode(mesh);
|
||||
if (node)
|
||||
{
|
||||
node->setPosition(vector3df(20, 0, 30));
|
||||
node->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
node->setDebugDataVisible(scene::EDS_NORMALS);
|
||||
node->setMaterialTexture(0, driver->getTexture("../media/sydney.bmp"));
|
||||
node->setLoopMode(false);
|
||||
|
||||
(void)smgr->addCameraSceneNode();
|
||||
|
||||
node->setMD2Animation(scene::EMAT_STAND);
|
||||
node->setAnimationSpeed(0);
|
||||
device->run();
|
||||
driver->beginScene(true, true, video::SColor(255, 255, 255, 0));
|
||||
smgr->drawAll();
|
||||
driver->endScene();
|
||||
}
|
||||
}
|
||||
|
||||
result &= takeScreenshotAndCompareAgainstReference(driver, "-md2Normals.png");
|
||||
device->closeDevice();
|
||||
device->run();
|
||||
device->drop();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// test md2 features
|
||||
bool md2Animation(void)
|
||||
{
|
||||
bool result = testLastFrame();
|
||||
result &= testNormals();
|
||||
return result;
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 6.3 KiB |
|
@ -59,6 +59,164 @@ static bool testGetIntersectionWithLine(core::triangle3d<T>& triangle, const cor
|
|||
return allExpected;
|
||||
}
|
||||
|
||||
// modifying the same triangle in diverse ways get some more test-cases automatically
|
||||
template<class T>
|
||||
static bool stageModifications(int stage, triangle3d<T>& triangle)
|
||||
{
|
||||
switch ( stage )
|
||||
{
|
||||
case 0:
|
||||
return true;
|
||||
case 1:
|
||||
swap(triangle.pointB, triangle.pointC);
|
||||
return true;
|
||||
case 2:
|
||||
swap(triangle.pointA, triangle.pointC);
|
||||
return true;
|
||||
case 3:
|
||||
triangle.pointA.Z += 1000;
|
||||
triangle.pointB.Z += 1000;
|
||||
triangle.pointC.Z += 1000;
|
||||
return true;
|
||||
case 4:
|
||||
swap(triangle.pointA.Y, triangle.pointA.Z);
|
||||
swap(triangle.pointB.Y, triangle.pointB.Z);
|
||||
swap(triangle.pointC.Y, triangle.pointC.Z);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void stageModifications(int stage, vector3d<T>& point)
|
||||
{
|
||||
switch ( stage )
|
||||
{
|
||||
case 3:
|
||||
point.Z += 1000;
|
||||
break;
|
||||
case 4:
|
||||
swap(point.Y, point.Z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static bool isPointInside(triangle3d<T> triangleOrig)
|
||||
{
|
||||
bool allExpected=true;
|
||||
|
||||
array< vector3d<T> > pointsInside;
|
||||
pointsInside.push_back( vector3d<T>(0,0,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointB + triangleOrig.pointC) / 3 );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 + vector3d<T>(0,1,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 + vector3d<T>(1,0,0) );
|
||||
pointsInside.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 - vector3d<T>(1,0,0) );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsInside.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsInside[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsInside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
allExpected &= triangle.isPointInsideFast( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInsideFast pointsInside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array< vector3d<T> > pointsOutside;
|
||||
pointsOutside.push_back( triangleOrig.pointA - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointA - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointB + vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointB - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC + vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( triangleOrig.pointC + vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 - vector3d<T>(0,1,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 - vector3d<T>(1,0,0) );
|
||||
pointsOutside.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 + vector3d<T>(1,0,0) );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsOutside.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsOutside[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= !triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsOutside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
allExpected &= !triangle.isPointInsideFast( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInsideFast pointsOutside test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array< vector3d<T> > pointsBorder;
|
||||
pointsBorder.push_back( triangleOrig.pointA );
|
||||
pointsBorder.push_back( triangleOrig.pointB );
|
||||
pointsBorder.push_back( triangleOrig.pointC );
|
||||
pointsBorder.push_back( (triangleOrig.pointA + triangleOrig.pointB)/2 );
|
||||
pointsBorder.push_back( (triangleOrig.pointA + triangleOrig.pointC)/2 );
|
||||
pointsBorder.push_back( (triangleOrig.pointB + triangleOrig.pointC)/2 );
|
||||
|
||||
for (u32 stage=0; ; ++stage)
|
||||
{
|
||||
triangle3d<T> triangle = triangleOrig;
|
||||
if ( !stageModifications(stage, triangle) )
|
||||
break;
|
||||
|
||||
for ( u32 i=0; i < pointsBorder.size(); ++i )
|
||||
{
|
||||
vector3d<T> point = pointsBorder[i];
|
||||
stageModifications(stage, point);
|
||||
|
||||
allExpected &= triangle.isPointInside( point );
|
||||
if ( !allExpected )
|
||||
{
|
||||
logTestString("triangle3d::isPointInside pointsBorder test failed in stage %d point %d\n", stage, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* results for isPointInsideFast are mixed for border cases, but I guess that's fine.
|
||||
if ( triangle.isPointInsideFast( point ) )
|
||||
logTestString("+ triangle3d::isPointInsideFast pointsBorder stage %d point %d is INSIDE\n", stage, i);
|
||||
else
|
||||
logTestString("- triangle3d::isPointInsideFast pointsBorder stage %d point %d is NOT inside\n", stage, i);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return allExpected;
|
||||
}
|
||||
|
||||
|
||||
// Test the functionality of triangle3d<T>
|
||||
/** Validation is done with asserts() against expected results. */
|
||||
|
@ -89,6 +247,29 @@ bool testTriangle3d(void)
|
|||
allExpected &= testGetIntersectionWithLine(triangle, ray);
|
||||
}
|
||||
|
||||
bool testEigen = triangle3di(vector3di(250, 0, 0), vector3di(0, 0, 500), vector3di(500, 0, 500)).isPointInside(vector3di(300,0,300));
|
||||
if ( !testEigen ) // test from Eigen from here: http://irrlicht.sourceforge.net/forum/viewtopic.php?f=7&t=44372&p=254331#p254331
|
||||
logTestString("Test isPointInside fails with integers\n");
|
||||
allExpected &= testEigen;
|
||||
|
||||
logTestString("Test isPointInside with f32\n");
|
||||
{
|
||||
triangle3d<f32> t(vector3d<f32>(-1000,-1000,0), vector3d<f32>(1000,-1000,0), vector3d<f32>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
logTestString("Test isPointInside with f64\n");
|
||||
{
|
||||
triangle3d<f64> t(vector3d<f64>(-1000,-1000,0), vector3d<f64>(1000,-1000,0), vector3d<f64>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
logTestString("Test isPointInside with s32\n");
|
||||
{
|
||||
triangle3d<s32> t(vector3d<s32>(-1000,-1000,0), vector3d<s32>(1000,-1000,0), vector3d<s32>(0,1000,0));
|
||||
allExpected &= isPointInside(t);
|
||||
}
|
||||
|
||||
if(allExpected)
|
||||
logTestString("\nAll tests passed\n");
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue