TEST( Transform, inversion ) { // let's create a transform, then create its inverse and multiply the two. // they should add up to an identity transformation Transform transform; { transform.m_rotation.setAxisAngle( Quad_1000, FastFloat::fromFloat( DEG2RAD( 45.0f ) ) ); transform.m_translation.set( 2, 0, 0 ); } Transform invTransform; invTransform.setInverse( transform ); Transform concatenatedTransformA; concatenatedTransformA.setMul( transform, invTransform ); // no matter what order we multiply the component transforms in, it should always result in an identity transform Transform concatenatedTransformB; concatenatedTransformB.setMul( invTransform , transform ); COMPARE_QUAT( concatenatedTransformA.m_rotation, concatenatedTransformB.m_rotation ); COMPARE_QUAT( Quaternion::IDENTITY, concatenatedTransformB.m_rotation ); COMPARE_VEC( concatenatedTransformA.m_translation, concatenatedTransformB.m_translation ); COMPARE_VEC( Vector( Quad_0 ), concatenatedTransformB.m_translation ); }
TEST( BoneSRTAnimation, simpleTranslationAnim ) { BoneSRTAnimation anim; anim.addTranslationKey( 0, Quad_0 ); anim.addTranslationKey( 1, Quad_1000 ); CPPUNIT_ASSERT_EQUAL( 1.0f, anim.getDuration() ); BoneSRTAnimationPlayer player( anim ); Vector result; CPPUNIT_ASSERT( player.getTranslation( 0.0f, result ) ); COMPARE_VEC( Vector( 0, 0, 0 ), result ); CPPUNIT_ASSERT( player.getTranslation( 1.0f, result ) ); COMPARE_VEC( Vector( 1, 0, 0 ), result ); CPPUNIT_ASSERT( player.getTranslation( 0.5f, result ) ); COMPARE_VEC( Vector( 0.5f, 0, 0 ), result ); // outside the boundaries access - return the boundary values, don't perform any looped lookups CPPUNIT_ASSERT( player.getTranslation( -0.1f, result ) ); COMPARE_VEC( Vector( 0, 0, 0 ), result ); CPPUNIT_ASSERT( player.getTranslation( 1.1f, result ) ); COMPARE_VEC( Vector( 1, 0, 0 ), result ); }
TEST( TriangleSplitter, nonStandardTriangle ) { Triangle vol(Vector(-1.5f, 0, 1), Vector( 2.5f, 0, 2.5f), Vector( 0.5f, 0,-2.5f)); Array<Triangle*> frontSplit; Array<Triangle*> backSplit; Plane plane; plane.set( Quad_1000, FastFloat::fromFloat( -1.5f ) ); vol.split( plane, frontSplit, backSplit ); CPPUNIT_ASSERT_EQUAL((unsigned int)1, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)2, backSplit.size()); COMPARE_VEC(Vector(1.5f, 0, 2.125f), frontSplit[0]->vertex(0)); COMPARE_VEC(Vector(2.5f, 0, 2.5f), frontSplit[0]->vertex(1)); COMPARE_VEC(Vector(1.5f, 0, 0), frontSplit[0]->vertex(2)); COMPARE_VEC(Vector(-1.5f, 0, 1), backSplit[0]->vertex(0)); COMPARE_VEC(Vector( 1.5f, 0, 2.125f), backSplit[0]->vertex(1)); COMPARE_VEC(Vector( 1.5f, 0, 0), backSplit[0]->vertex(2)); COMPARE_VEC(Vector(-1.5f, 0, 1), backSplit[1]->vertex(0)); COMPARE_VEC(Vector( 1.5f, 0, 0), backSplit[1]->vertex(1)); COMPARE_VEC(Vector( 0.5f, 0,-2.5f), backSplit[1]->vertex(2)); delete backSplit[0]; delete backSplit[1]; delete frontSplit[0]; }
TEST( TriangleSplitter, cuttingTriangleThroughTwoEdges ) { Triangle vol(Vector(-1, 0, 1), Vector(1, 0, 1), Vector(-1, 0, -1)); Array<Triangle*> frontSplit; Array<Triangle*> backSplit; Plane plane; plane.set( Float_1, Float_0, Float_0, Float_0 ); vol.split( plane, frontSplit, backSplit ); CPPUNIT_ASSERT_EQUAL((unsigned int)1, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)2, backSplit.size()); COMPARE_VEC(Vector( 0, 0, 1), frontSplit[0]->vertex(0)); COMPARE_VEC(Vector( 1, 0, 1), frontSplit[0]->vertex(1)); COMPARE_VEC(Vector( 0, 0, 0), frontSplit[0]->vertex(2)); COMPARE_VEC(Vector(-1, 0, 1), backSplit[0]->vertex(0)); COMPARE_VEC(Vector( 0, 0, 1), backSplit[0]->vertex(1)); COMPARE_VEC(Vector( 0, 0, 0), backSplit[0]->vertex(2)); COMPARE_VEC(Vector(-1, 0, 1), backSplit[1]->vertex(0)); COMPARE_VEC(Vector( 0, 0, 0), backSplit[1]->vertex(1)); COMPARE_VEC(Vector(-1, 0, -1), backSplit[1]->vertex(2)); delete backSplit[0]; delete backSplit[1]; delete frontSplit[0]; }
TEST( TriangleSplitter, bugTriangle ) { Triangle vol(Vector( 11, -29, 2), Vector( 11, -29, -2), Vector( 0, -29, -2)); Array<Triangle*> frontSplit; Array<Triangle*> backSplit; Plane plane; plane.set( Float_0, Float_0, Float_1, Float_0 ); vol.split(plane, frontSplit, backSplit); CPPUNIT_ASSERT_EQUAL((unsigned int)1, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)2, backSplit.size()); COMPARE_VEC(Vector( 11, -29, 2), frontSplit[0]->vertex(0)); COMPARE_VEC(Vector( 11, -29, 0), frontSplit[0]->vertex(1)); COMPARE_VEC(Vector(5.5f, -29, 0), frontSplit[0]->vertex(2)); COMPARE_VEC(Vector( 11, -29, 0), backSplit[0]->vertex(0)); COMPARE_VEC(Vector( 11, -29, -2), backSplit[0]->vertex(1)); COMPARE_VEC(Vector( 0, -29, -2), backSplit[0]->vertex(2)); COMPARE_VEC(Vector( 11, -29, 0), backSplit[1]->vertex(0)); COMPARE_VEC(Vector( 0, -29, -2), backSplit[1]->vertex(1)); COMPARE_VEC(Vector(5.5f, -29, 0), backSplit[1]->vertex(2)); delete backSplit[0]; delete backSplit[1]; delete frontSplit[0]; }
TEST(Camera, createRay) { RendererImplementationMock renderer; Camera camera( "camera", renderer, Camera::PT_PERSPECTIVE); Frustum frustum; camera.calculateFrustum( frustum ); Vector expectedNormal; // a basic plane running straight through the screen's center Ray result; camera.createRay( 0, 0, result ); COMPARE_VEC( Vector(0, 0, 0), result.origin ); COMPARE_VEC( Vector(0, 0, 1), result.direction ); // test the rays running through the frustum's clipping planes: // - bottom plane Vector planeNormal; frustum.planes[FP_BOTTOM].getNormal( planeNormal ); expectedNormal.setCross( planeNormal, Quad_Neg_1000 ); expectedNormal.normalize(); camera.createRay( 0, -1, result ); COMPARE_VEC(Vector(0, 0, 0), result.origin); COMPARE_VEC(expectedNormal, result.direction); // - top plane frustum.planes[FP_TOP].getNormal( planeNormal ); expectedNormal.setCross( planeNormal, Quad_1000 ); expectedNormal.normalize(); camera.createRay( 0, 1, result ); COMPARE_VEC(Vector(0, 0, 0), result.origin); COMPARE_VEC(expectedNormal, result.direction); // - left plane frustum.planes[FP_LEFT].getNormal( planeNormal ); expectedNormal.setCross( Quad_Neg_0100, planeNormal ); expectedNormal.normalize(); camera.createRay( -1, 0, result ); COMPARE_VEC(Vector(0, 0, 0), result.origin); COMPARE_VEC(expectedNormal, result.direction); // - right plane frustum.planes[FP_RIGHT].getNormal( planeNormal ); expectedNormal.setCross( Quad_0100, planeNormal ); expectedNormal.normalize(); camera.createRay( 1, 0, result ); COMPARE_VEC(Vector(0, 0, 0), result.origin); COMPARE_VEC(expectedNormal, result.direction); }
TEST( Transform, matrixConversion ) { // construct a transformation matrix we'll use for testing Matrix templateTranslationMtx; Quaternion testRot; Vector testTrans; { testRot.setAxisAngle( Quad_1000, FastFloat::fromFloat( DEG2RAD( 90.0f ) ) ); templateTranslationMtx.setRotation( testRot ); Matrix translationMtx; testTrans.set( 10, 20, 30 ); translationMtx.setTranslation( testTrans ); templateTranslationMtx.mul( translationMtx ); } // first create a transform from the matrix Transform transform; transform.set( templateTranslationMtx ); COMPARE_QUAT( testRot, transform.m_rotation ); COMPARE_VEC( testTrans, transform.m_translation ); // and then convert that transform back to a matrix form Matrix recoveredMtx; transform.toMatrix( recoveredMtx ); COMPARE_MTX( templateTranslationMtx, recoveredMtx ); }
TEST( Box, offsetCollision ) { Box b1, b2; Matrix transform; IntersectionResult contactPointsArr[8]; transform.setAxisAnglePos( Vector_OX, FastFloat::fromFloat( DEG2RAD( 45.0f ) ), Vector( 0.0f, 0.0f, 4.0f ) ); b1.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); transform.setTranslation( Vector( 0.0f, 0.0f, 3.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( ( uint ) 2, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( -0.5f, 0.0f, 3.2929f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_OZ, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.0f, 3.2929f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_OZ, contactPointsArr[1].m_contactNormal ); }
TEST( MatrixUtils, generateLookAtLH ) { Matrix tamyLookAtMtx; Vector cameraOriginPos( 10, 20, -30 ); Vector lookAtPos( 15, 20, -30 ); Vector upAxis; upAxis.set( Quad_0100 ); MatrixUtils::generateLookAtLH( cameraOriginPos, lookAtPos, upAxis, tamyLookAtMtx ); Vector expectedLookVec; expectedLookVec.setSub( lookAtPos, cameraOriginPos ); expectedLookVec.normalize(); Vector transformedLookVec; tamyLookAtMtx.transformNorm( Vector( 0, 0, 1 ), transformedLookVec ); COMPARE_VEC( cameraOriginPos, tamyLookAtMtx.position() ); COMPARE_VEC( expectedLookVec, transformedLookVec ); }
TEST( Box, edgeCollision ) { Box b1, b2; Matrix transform; IntersectionResult contactPointsArr[8]; Quaternion rot; rot.setAxisAngle( Vector_OZ, FastFloat::fromFloat( DEG2RAD( 45.0f ) ) ); transform.setRotation( rot ); transform.setPosition<3>( Vector( 0.75f, 0.0f, 0.0f ) ); b1.set( Vector( 1.0f, 1.0f, 0.2f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( ( uint )2, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, 0.0f, -0.1f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.0f, 0.1f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[1].m_contactNormal ); }
TEST( TriangleSplitter, planeIsOnOneOfTheVertices ) { Triangle vol(Vector(-1, 0, 1), Vector(1, 0, 1), Vector(0, 0, 0)); Array<Triangle*> frontSplit; Array<Triangle*> backSplit; Plane plane; plane.set( Float_0, Float_0, Float_1, Float_0 ); vol.split(plane, frontSplit, backSplit); CPPUNIT_ASSERT_EQUAL((unsigned int)1, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)0, backSplit.size()); COMPARE_VEC(Vector(-1, 0, 1), frontSplit[0]->vertex(0)); COMPARE_VEC(Vector( 1, 0, 1), frontSplit[0]->vertex(1)); COMPARE_VEC(Vector( 0, 0, 0), frontSplit[0]->vertex(2)); delete frontSplit[0]; }
TEST( BoneSRTAnimation, replacingAnimKeys ) { BoneSRTAnimation anim; anim.addTranslationKey( 0, Vector( 0, 0, 0 ) ); anim.addTranslationKey( 1, Vector( 1, 0, 0 ) ); anim.addTranslationKey( 1, Vector( 2, 0, 0 ) ); CPPUNIT_ASSERT_EQUAL( 1.0f, anim.getDuration() ); BoneSRTAnimationPlayer player( anim ); Vector result; CPPUNIT_ASSERT( player.getTranslation( 0.0f, result ) ); COMPARE_VEC( Vector( 0, 0, 0 ), result ); CPPUNIT_ASSERT( player.getTranslation( 0.5f, result ) ); COMPARE_VEC( Vector( 1.0f, 0, 0 ), result ); CPPUNIT_ASSERT( player.getTranslation( 1.0f, result ) ); COMPARE_VEC( Vector( 2.0f, 0, 0 ), result ); }
TEST( AxisAlignedBox, transformation ) { AxisAlignedBox centralBB( Vector( -1, -1, -1 ), Vector( 1, 1, 1 ) ); Transform transform; Matrix transformMtx; AxisAlignedBox transformedBB; { transform.m_rotation.setAxisAngle( Vector_OZ, FastFloat::fromFloat( DEG2RAD( 45.0f ) ) ); transform.toMatrix( transformMtx ); centralBB.transform( transformMtx, transformedBB ); COMPARE_VEC( Vector( -1.4142135f, -1.4142135f, -1 ), transformedBB.min ); COMPARE_VEC( Vector( 1.4142135f, 1.4142135f, 1 ), transformedBB.max ); } { transform.m_rotation.setAxisAngle( Vector_OX, FastFloat::fromFloat( DEG2RAD( 45.0f ) ) ); transform.toMatrix( transformMtx ); centralBB.transform( transformMtx, transformedBB ); COMPARE_VEC( Vector( -1, -1.4142135f, -1.4142135f ), transformedBB.min ); COMPARE_VEC( Vector( 1, 1.4142135f, 1.4142135f ), transformedBB.max ); } { transform.m_rotation.setAxisAngle( Vector_OY, FastFloat::fromFloat( DEG2RAD( 45.0f ) ) ); transform.toMatrix( transformMtx ); centralBB.transform( transformMtx, transformedBB ); COMPARE_VEC( Vector( -1.4142135f, -1, -1.4142135f ), transformedBB.min ); COMPARE_VEC( Vector( 1.4142135f, 1, 1.4142135f ), transformedBB.max ); } }
TEST(CompositeSteeringBehavior, mixingBehaviors) { Vector testPos; CompositeSteeringBehavior composite; testPos.set( 10, 0, 0 ); composite.add( new SteeringBehaviorMock( testPos ), 0.5 ); testPos.set( 0, 10, 0 ); composite.add( new SteeringBehaviorMock( testPos ), 1 ); Vector outVel; composite.calculateVelocity( 1, outVel ); testPos.set( 5, 10, 0 ); COMPARE_VEC( testPos, outVel ); }
TEST( Frustum, frustumBoundingBox ) { RendererImplementationMock renderer; Camera camera( "camera", renderer, Camera::PT_PERSPECTIVE ); camera.setNearPlaneDimensions(10, 10); camera.setClippingPlanes(10, 100); camera.setFOV(90); Frustum frustum; AABoundingBox frustumBounds; Transform cameraTransform; // identity matrix camera.calculateFrustum( frustum ); frustum.calculateBoundingBox( frustumBounds ); COMPARE_VEC( Vector( -100.0f, -100.0f, 10.0f ), frustumBounds.min ); COMPARE_VEC( Vector( 100.0f, 100.0f, 100.0f ), frustumBounds.max ); // changed position cameraTransform.m_translation.set( 10, 20, 30 ); cameraTransform.toMatrix( camera.accessLocalMtx() ); camera.calculateFrustum( frustum ); frustum.calculateBoundingBox( frustumBounds ); COMPARE_VEC( Vector( -90.0f, -80.0f, 40.0f ), frustumBounds.min ); COMPARE_VEC( Vector( 110.0f, 120.0f, 130.0f ), frustumBounds.max ); // rotated & translated camera cameraTransform.m_rotation.setAxisAngle( Vector_OY, FastFloat::fromFloat( DEG2RAD( 90 ) ) ); cameraTransform.toMatrix( camera.accessLocalMtx() ); camera.calculateFrustum( frustum ); frustum.calculateBoundingBox( frustumBounds ); COMPARE_VEC( Vector( 20.0f, -80.0f, -70.0f ), frustumBounds.min ); COMPARE_VEC( Vector( 110.0f, 120.0f, 130.0f ), frustumBounds.max ); // rotated camera cameraTransform.m_translation.set( 0, 0, 0 ); cameraTransform.toMatrix( camera.accessLocalMtx() ); camera.calculateFrustum( frustum ); frustum.calculateBoundingBox( frustumBounds ); COMPARE_VEC( Vector( 10.0f, -100.0f, -100.0f ), frustumBounds.min ); COMPARE_VEC( Vector( 100.0f, 100.0f, 100.0f ), frustumBounds.max ); }
TEST( Box, faceCollision ) { Box b1, b2; Matrix transform; IntersectionResult contactPointsArr[8]; transform.setTranslation( Vector( 0.75f, 0.0f, 0.0f ) ); b1.set( Vector( 1.0f, 5.0f, 5.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( ( uint ) 4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, -0.5f, -0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, -0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[3].m_contactNormal ); }
TEST( Transform, normalTransformation ) { // construct a transformation we'll use for testing Transform trans; { trans.m_rotation.setAxisAngle( Quad_1000, FastFloat::fromFloat( DEG2RAD( 90.0f ) ) ); trans.m_translation.set( 10, 20, 30 ); } // create the test vector Vector testVec( 0, 1, 0 ); // transform the vector Vector transformedVec; trans.transformNorm( testVec, transformedVec ); // the transform should: // 1. rotate the vector around the X axis, transforming it to ( 0, 0, 1 ) // 2. doesn't translate it COMPARE_VEC( Vector( 0, 0, 1 ), transformedVec ); }
TEST( TriangleSplitter, notCuttingPlaneUsed ) { Triangle vol(Vector(-1, 0, 1), Vector(1, 0, 1), Vector(-1, 0, -1)); // plane that the triangle is behind Array<Triangle*> frontSplit; Array<Triangle*> backSplit; Plane plane; plane.set( Float_0, Float_0, Float_1, Float_Minus2 ); vol.split(plane, frontSplit, backSplit); CPPUNIT_ASSERT_EQUAL((unsigned int)0, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)1, backSplit.size()); CPPUNIT_ASSERT(NULL != backSplit[0]); COMPARE_VEC(Vector(-1, 0, 1), backSplit[0]->vertex(0)); COMPARE_VEC(Vector( 1, 0, 1), backSplit[0]->vertex(1)); COMPARE_VEC(Vector(-1, 0, -1), backSplit[0]->vertex(2)); delete backSplit[0]; backSplit.clear(); // plane that the triangle is in front of plane.set( Float_0, Float_0, Float_1, Float_2 ); vol.split( plane, frontSplit, backSplit); CPPUNIT_ASSERT_EQUAL((unsigned int)1, frontSplit.size()); CPPUNIT_ASSERT_EQUAL((unsigned int)0, backSplit.size()); CPPUNIT_ASSERT(NULL != frontSplit[0]); COMPARE_VEC(Vector(-1, 0, 1), frontSplit[0]->vertex(0)); COMPARE_VEC(Vector( 1, 0, 1), frontSplit[0]->vertex(1)); COMPARE_VEC(Vector(-1, 0, -1), frontSplit[0]->vertex(2)); delete frontSplit[0]; }
TEST( Box, vertexCollision ) { Box b1, b2; Matrix transform; IntersectionResult contactPointsArr[8]; // axis aligned boxes, colliding { b1.set( Vector( 1.0f, 1.0f, 1.0f ) ); // face-face collision // NOTE: when two bodies collide, two sets of contact points should be generated, that would affect each body individually. // But the fact is that we can do only with one set of contact points just for one body, 'cause one for the other one // is just a reflection of the first set. // So the convention is that if we call bodyA.testIntersection( bodyB ), the returned contact points // will refer to bodyA. If it's bodyB we want to move in response to the contact point, we just need // to calculate a mirror reflection of it. // box slides along the x axis transform.setTranslation( Vector( -0.5f, 0.75f, 0.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( -0.5f, 0.5f, 0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.0f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.0f, 0.5f, -0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, 0.5f, -0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.0f, 0.75f, 0.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( -0.5f, 0.5f, -0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, -0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.5f, 0.75f, 0.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.0f, 0.5f, -0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, -0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.0f, 0.5f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OY, contactPointsArr[3].m_contactNormal ); // now it slides along the y axis transform.setTranslation( Vector( 0.0f, -0.5f, 0.75f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.0f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, 0.0f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, -0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.0f, 0.0f, 0.75f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( -0.5f, -0.5f, 0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.0f, 0.5f, 0.75f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( -0.5f, 0.0f, 0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( -0.5f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.0f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OZ, contactPointsArr[3].m_contactNormal ); // and finally - along the z axis transform.setTranslation( Vector( 0.75f, 0.0f, -0.5f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.0f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, -0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, -0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.0f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.75f, 0.0f, 0.0f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, -0.5f, -0.5f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.5f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, -0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[3].m_contactNormal ); transform.setTranslation( Vector( 0.75f, 0.0f, 0.5f ) ); b2.set( Vector( 1.0f, 1.0f, 1.0f ), transform ); CPPUNIT_ASSERT_EQUAL( (uint)4, b1.testIntersection( b2, contactPointsArr, 8 ) ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.0f ), contactPointsArr[0].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[0].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, -0.5f, 0.5f ), contactPointsArr[1].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[1].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.0f ), contactPointsArr[2].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[2].m_contactNormal ); COMPARE_VEC( Vector( 0.5f, 0.5f, 0.5f ), contactPointsArr[3].m_contactPoint ); COMPARE_VEC( Vector_NEG_OX, contactPointsArr[3].m_contactNormal ); } }
TEST( SnapshotAnimation, build ) { // build a test animation const uint bonesCount = 2; BoneSRTAnimation* keyframes = new BoneSRTAnimation[bonesCount]; BoneSRTAnimation motion; { // frame 0 keyframes[0].addTranslationKey( 0.0f, Vector_ZERO ); keyframes[1].addTranslationKey( 0.0f, Vector_ZERO ); motion.addTranslationKey( 0.0f, Vector_ZERO ); keyframes[0].addTranslationKey( 0.75f, Vector( 3.75f, 0, 0 ) ); keyframes[1].addTranslationKey( 1.0f, Vector( 0, 5, 0 ) ); motion.addTranslationKey( 0.8f, Vector( 0, 0, 4 ) ); } SnapshotAnimation animation; SnapshotAnimation::build( animation, bonesCount, keyframes, motion ); { CPPUNIT_ASSERT_EQUAL( 1.0f, animation.m_duration ); CPPUNIT_ASSERT_EQUAL( bonesCount, animation.m_bonesCount ); CPPUNIT_ASSERT_EQUAL( (uint)50, animation.m_poseTracks.size() ); // the animation is 1s long and we were sampling at 24 frames/sec, so we have 25 key frames per bone, which gives 50 frames for a skeleton that consists of 2 bones CPPUNIT_ASSERT_EQUAL( (uint)25, animation.m_motionTrack.size() ); // and 25 keyframes in the motion track } // test the animation { Transform boneTransforms[2]; Transform motionTransform; { animation.samplePose( 0.0f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 0.0f, motionTransform ); COMPARE_VEC( Vector_ZERO, boneTransforms[0].m_translation ); COMPARE_VEC( Vector_ZERO, boneTransforms[1].m_translation ); COMPARE_VEC( Vector_ZERO, motionTransform.m_translation ); } { animation.samplePose( 0.25f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 0.25f, motionTransform ); COMPARE_VEC( Vector( 1.25f, 0, 0 ), boneTransforms[0].m_translation ); COMPARE_VEC( Vector( 0, 1.25f, 0 ), boneTransforms[1].m_translation ); COMPARE_VEC( Vector( 0, 0, 1.25f ), motionTransform.m_translation ); } { animation.samplePose( 0.5f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 0.5f, motionTransform ); COMPARE_VEC( Vector( 2.5f, 0, 0 ), boneTransforms[0].m_translation ); COMPARE_VEC( Vector( 0, 2.5f, 0 ), boneTransforms[1].m_translation ); COMPARE_VEC( Vector( 0, 0, 2.5f ), motionTransform.m_translation ); } { animation.samplePose( 0.75f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 0.75f, motionTransform ); COMPARE_VEC( Vector( 3.75f, 0, 0 ), boneTransforms[0].m_translation ); COMPARE_VEC( Vector( 0, 3.75f, 0 ), boneTransforms[1].m_translation ); COMPARE_VEC( Vector( 0, 0, 3.75f ), motionTransform.m_translation ); } { animation.samplePose( 1.0f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 1.0f, motionTransform ); COMPARE_VEC( Vector( 3.75f, 0, 0 ), boneTransforms[0].m_translation ); COMPARE_VEC( Vector( 0, 5, 0 ), boneTransforms[1].m_translation ); COMPARE_VEC( Vector( 0, 0, 4 ), motionTransform.m_translation ); } // test outside of the boundaries { animation.samplePose( -0.1f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, -0.1f, motionTransform ); COMPARE_VEC( Vector_ZERO, boneTransforms[0].m_translation ); COMPARE_VEC( Vector_ZERO, boneTransforms[1].m_translation ); COMPARE_VEC( Vector_ZERO, motionTransform.m_translation ); } { animation.samplePose( 1.1f, boneTransforms, 2 ); animation.sampleMotion( 0.0f, 1.1f, motionTransform ); COMPARE_VEC( Vector( 3.75f, 0, 0 ), boneTransforms[0].m_translation ); COMPARE_VEC( Vector( 0, 5, 0 ), boneTransforms[1].m_translation ); COMPARE_VEC( Vector( 0, 0, 4 ), motionTransform.m_translation ); } } // cleanup delete [] keyframes; }