TEST(ReachabilitySphere, fitCylinder_2) { Capability cylinder1(CYLINDER_2, 90.0, 90.0, 20.0); ReachabilitySphere sphere = createReachabilitySphereFromCapability(cylinder1, 200); // convert phi and theta to coordinates double phiInRad = 90.0 * M_PI / 180.0; double thetaInRad = 90.0 * M_PI / 180.0; Vector axis; axis.x = sin(thetaInRad) * cos(phiInRad); axis.y = sin(thetaInRad) * sin(phiInRad); axis.z = cos(thetaInRad); std::pair<double, double> angleAndSFE = sphere.fitCylinder_2(axis); ASSERT_TRUE(angleAndSFE.first < 20.01); ASSERT_TRUE(angleAndSFE.first > 19.0); ASSERT_EQ(angleAndSFE.second, 0.0); Capability cylinder2(CYLINDER_2, 320.0, 35.0, 40.0); sphere = createReachabilitySphereFromCapability(cylinder2, 200); // convert phi and theta to coordinates phiInRad = 320.0 * M_PI / 180.0; thetaInRad = 35.0 * M_PI / 180.0; axis.x = sin(thetaInRad) * cos(phiInRad); axis.y = sin(thetaInRad) * sin(phiInRad); axis.z = cos(thetaInRad); angleAndSFE = sphere.fitCylinder_2(axis); ASSERT_TRUE(angleAndSFE.first < 40.01 && angleAndSFE.first > 39.0); ASSERT_EQ(angleAndSFE.second, 0.0); // check that cylinder_1 is matched too if axis points to opposite direction Capability cylinder3(CYLINDER_2, 0.0, 0.0, 20.0); sphere = createReachabilitySphereFromCapability(cylinder3, 200); // convert phi and theta to coordinates phiInRad = 0.0 * M_PI / 180.0; thetaInRad = 180.0 * M_PI / 180.0; axis.x = sin(thetaInRad) * cos(phiInRad); axis.y = sin(thetaInRad) * sin(phiInRad); axis.z = cos(thetaInRad); angleAndSFE = sphere.fitCylinder_2(axis); ASSERT_TRUE(angleAndSFE.first < 20.0); ASSERT_EQ(angleAndSFE.second, 0.0); // check if SFE grows if axis is not alligned correctly Capability cylinder4(CYLINDER_2, 0.0, 0.0, 20.0); sphere = createReachabilitySphereFromCapability(cylinder4, 200); // convert phi and theta to coordinates phiInRad = 0.0 * M_PI / 180.0; thetaInRad = 10.0 * M_PI / 180.0; axis.x = sin(thetaInRad) * cos(phiInRad); axis.y = sin(thetaInRad) * sin(phiInRad); axis.z = cos(thetaInRad); angleAndSFE = sphere.fitCylinder_2(axis); ASSERT_TRUE(angleAndSFE.second > 0.0); }
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, INT ) { srand( static_cast<unsigned>( time(NULL) ) ); SkinningVertex * cylinder_vertices = NULL; Index * cylinder_indices = NULL; Vertex * tesselated_vertices = NULL; Index * tesselated_indices = NULL; try { Application app; VertexShader skinning_shader(app.get_device(), SKINNING_VERTEX_DECL_ARRAY, SKINNING_SHADER_FILENAME); VertexShader morphing_shader(app.get_device(), VERTEX_DECL_ARRAY, MORPHING_SHADER_FILENAME); // -------------------------- C y l i n d e r ----------------------- cylinder_vertices = new SkinningVertex[CYLINDER_VERTICES_COUNT]; cylinder_indices = new Index[CYLINDER_INDICES_COUNT]; float height = 2.0f; cylinder( 0.7f, height, colors, colors_count, cylinder_vertices, cylinder_indices ); SkinningModel cylinder1(app.get_device(), D3DPT_TRIANGLESTRIP, skinning_shader, cylinder_vertices, CYLINDER_VERTICES_COUNT, cylinder_indices, CYLINDER_INDICES_COUNT, CYLINDER_INDICES_COUNT - 2, D3DXVECTOR3(0.5f, 0.5f, -height/2), D3DXVECTOR3(0,0,0), D3DXVECTOR3(0,0,-1)); height = 2.3f; cylinder( 0.3f, height, &SECOND_CYLINDER_COLOR, 1, cylinder_vertices, cylinder_indices ); SkinningModel cylinder2(app.get_device(), D3DPT_TRIANGLESTRIP, skinning_shader, cylinder_vertices, CYLINDER_VERTICES_COUNT, cylinder_indices, CYLINDER_INDICES_COUNT, CYLINDER_INDICES_COUNT - 2, D3DXVECTOR3(-1.0f, 0.5f, height/2), D3DXVECTOR3(D3DX_PI,0,-D3DX_PI/4), D3DXVECTOR3(0,0,1)); // -------------------------- P y r a m i d ----------------------- const Index PLANES_PER_PYRAMID = 8; const D3DXVECTOR3 normal_up(0,0,1); const Vertex pyramid_vertices[]= { Vertex(D3DXVECTOR3( 0.5f, -0.5f, 0.00f ),normal_up), Vertex(D3DXVECTOR3( -0.5f, -0.5f, 0.00f ),normal_up), Vertex(D3DXVECTOR3( -0.5f, 0.5f, 0.00f ),normal_up), Vertex(D3DXVECTOR3( 0.5f, 0.5f, 0.00f ),normal_up), Vertex(D3DXVECTOR3( 0.0f, 0.0f, 0.7071f ),normal_up), Vertex(D3DXVECTOR3( 0.0f, 0.0f, -0.7071f ),normal_up), }; const Index pyramid_indices[PLANES_PER_PYRAMID*VERTICES_PER_TRIANGLE] = { 0, 4, 3, 3, 4, 2, 2, 4, 1, 1, 4, 0, 0, 3, 5, 3, 2, 5, 2, 1, 5, 1, 0, 5, }; const Index ALL_TESSELATED_VERTICES_COUNT = PLANES_PER_PYRAMID*TESSELATED_VERTICES_COUNT; // per 8 tessellated triangles const DWORD ALL_TESSELATED_INDICES_COUNT = PLANES_PER_PYRAMID*TESSELATED_INDICES_COUNT; // per 8 tessellated triangles tesselated_vertices = new Vertex[ALL_TESSELATED_VERTICES_COUNT]; tesselated_indices = new Index[ALL_TESSELATED_INDICES_COUNT]; for( DWORD i = 0; i < PLANES_PER_PYRAMID; ++i ) { tessellate( pyramid_vertices, pyramid_indices, i*VERTICES_PER_TRIANGLE, &tesselated_vertices[i*TESSELATED_VERTICES_COUNT], i*TESSELATED_VERTICES_COUNT, &tesselated_indices[i*TESSELATED_INDICES_COUNT], SPHERE_COLOR ); } MorphingModel pyramid( app.get_device(), D3DPT_TRIANGLELIST, morphing_shader, tesselated_vertices, ALL_TESSELATED_VERTICES_COUNT, tesselated_indices, ALL_TESSELATED_INDICES_COUNT, ALL_TESSELATED_INDICES_COUNT/VERTICES_PER_TRIANGLE, D3DXVECTOR3(0, -1.3f, -0.2f), D3DXVECTOR3(0,0,0), 0.7071f); app.add_model(cylinder1); app.add_model(cylinder2); app.add_model(pyramid); app.run(); delete_array(&tesselated_indices); delete_array(&tesselated_vertices); delete_array(&cylinder_indices); delete_array(&cylinder_vertices); } catch(RuntimeError &e) { delete_array(&tesselated_indices); delete_array(&tesselated_vertices); delete_array(&cylinder_indices); delete_array(&cylinder_vertices); const TCHAR *MESSAGE_BOX_TITLE = _T("Lighting error!"); MessageBox(NULL, e.message(), MESSAGE_BOX_TITLE, MB_OK | MB_ICONERROR); return -1; } return 0; }
TEST(ReachabilitySphere, getPrincipalComponents) { ReachabilitySphere sphere; std::vector<Vector> vectors; std::vector<Vector> components; // a line in x direction should give the main principal component lying in x direction vectors.push_back(Vector(0.0, 0.0, 0.0)); vectors.push_back(Vector(1.0, 0.0, 0.0)); vectors.push_back(Vector(2.0, 0.0, 0.0)); vectors.push_back(Vector(3.0, 0.0, 0.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[2].x == 1.0); ASSERT_TRUE(components[2].y == 0.0); ASSERT_TRUE(components[2].z == 0.0); vectors.clear(); // a line in y direction should give the main principal component lying in y direction vectors.push_back(Vector(0.0, 0.0, 0.0)); vectors.push_back(Vector(0.0, 1.0, 0.0)); vectors.push_back(Vector(0.0, 2.0, 0.0)); vectors.push_back(Vector(0.0, 3.0, 0.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[2].x == 0.0); ASSERT_TRUE(components[2].y == 1.0); ASSERT_TRUE(components[2].z == 0.0); vectors.clear(); // a line in z direction should give the main principal component lying in z direction vectors.push_back(Vector(0.0, 0.0, 0.0)); vectors.push_back(Vector(0.0, 0.0, 1.0)); vectors.push_back(Vector(0.0, 0.0, 2.0)); vectors.push_back(Vector(0.0, 0.0, 3.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[2].x == 0.0); ASSERT_TRUE(components[2].y == 0.0); ASSERT_TRUE(components[2].z == 1.0); vectors.clear(); // filling just x and y directions should give the least principal component in z direction vectors.push_back(Vector(1.0, 2.0, 0.0)); vectors.push_back(Vector(2.0, 1.0, 0.0)); vectors.push_back(Vector(1.0, 0.0, 0.0)); vectors.push_back(Vector(0.0, 1.0, 0.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[0].x == 0.0); ASSERT_TRUE(components[0].y == 0.0); ASSERT_TRUE(components[0].z == 1.0); vectors.clear(); // filling just y and z directions should give the least principal component in x direction vectors.push_back(Vector(0.0, 2.0, 0.0)); vectors.push_back(Vector(0.0, 1.0, 2.0)); vectors.push_back(Vector(0.0, 0.0, 1.0)); vectors.push_back(Vector(0.0, 1.0, 1.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[0].x == 1.0); ASSERT_TRUE(components[0].y == 0.0); ASSERT_TRUE(components[0].z == 0.0); vectors.clear(); // filling just x and z directions should give the least principal component in y direction vectors.push_back(Vector(1.0, 0.0, 0.0)); vectors.push_back(Vector(2.0, 0.0, 2.0)); vectors.push_back(Vector(2.0, 0.0, 1.0)); vectors.push_back(Vector(0.0, 0.0, 1.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(components[0].x == 0.0); ASSERT_TRUE(components[0].y == 1.0); ASSERT_TRUE(components[0].z == 0.0); vectors.clear(); // a line in x-y direction should give the main principal component lying in x-y direction vectors.push_back(Vector(0.0, 0.0, 0.0)); vectors.push_back(Vector(1.0, 1.0, 0.0)); vectors.push_back(Vector(2.0, 2.0, 0.0)); vectors.push_back(Vector(3.0, 3.0, 0.0)); components = sphere.getPrincipalComponents(vectors); ASSERT_TRUE(fuzzyEquals(std::abs(components[2].x), 0.707106781)); ASSERT_TRUE(fuzzyEquals(std::abs(components[2].y), 0.707106781)); ASSERT_TRUE(components[2].z == 0.0); // test Capability of type cone Capability cone(CONE, 70.0, 55.0, 35.0); sphere = createReachabilitySphereFromCapability(cone, 400); components = sphere.getPrincipalComponents(sphere._reachableDirections); // test phi ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI < 72.0); ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI > 68.0); // test theta ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI < 56.0); ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI > 54.0); // test Capability of type cylinder_1 Capability cylinder1(CYLINDER_1, 70.0, 55.0, 35.0); sphere = createReachabilitySphereFromCapability(cylinder1, 400); components = sphere.getPrincipalComponents(sphere._reachableDirections); // test phi ASSERT_TRUE(atan2(components[2].y, components[2].x) * 180.0 / M_PI < 72.0); ASSERT_TRUE(atan2(components[2].y, components[2].x) * 180.0 / M_PI > 68.0); // test theta ASSERT_TRUE(acos(components[2].z) * 180.0 / M_PI < 56.0); ASSERT_TRUE(acos(components[2].z) * 180.0 / M_PI > 54.0); // test Capability of type cylinder_2 Capability cylinder2(CYLINDER_2, 70.0, 55.0, 35.0); sphere = createReachabilitySphereFromCapability(cylinder2, 400); components = sphere.getPrincipalComponents(sphere._reachableDirections); // test phi ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI < 72.0); ASSERT_TRUE(atan2(components[0].y, components[0].x) * 180.0 / M_PI > 68.0); // test theta ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI < 56.0); ASSERT_TRUE(acos(components[0].z) * 180.0 / M_PI > 54.0); }