diff --git a/tests/pe/CMakeLists.txt b/tests/pe/CMakeLists.txt index ca5346fa4ba72a701e6a77ed15f7dcdbce083cbe..9da367cc14f28a7966315d6a61f6690c9c97a46a 100644 --- a/tests/pe/CMakeLists.txt +++ b/tests/pe/CMakeLists.txt @@ -146,5 +146,14 @@ endif() waLBerla_compile_test( NAME PE_RAYTRACING FILES Raytracing.cpp DEPENDS core ) waLBerla_execute_test( NAME PE_RAYTRACING ) +waLBerla_compile_test( NAME PE_RAYTRACING_INTERSECTION FILES RaytracingIntersection.cpp DEPENDS core ) +waLBerla_execute_test( NAME PE_RAYTRACING_INTERSECTION ) + +waLBerla_compile_test( NAME PE_RAYTRACING_SPHERE FILES RaytracingSphere.cpp DEPENDS core ) +waLBerla_execute_test( NAME PE_RAYTRACING_SPHERE ) + +waLBerla_compile_test( NAME PE_RAYTRACING_HASHGRIDS FILES RaytracingHashGrids.cpp DEPENDS core ) +waLBerla_execute_test( NAME PE_RAYTRACING_HASHGRIDS ) + waLBerla_compile_test( NAME PE_VOLUMEINERTIA FILES VolumeInertia.cpp DEPENDS core ) waLBerla_execute_test( NAME PE_VOLUMEINERTIA CONFIGURATIONS Release RelWithDbgInfo) diff --git a/tests/pe/Raytracing.cpp b/tests/pe/Raytracing.cpp index f7aa2ca20cb45da786005f489e848f16f2bd6166..c060b997435308d8acd743496afcbc0bd94997ce 100644 --- a/tests/pe/Raytracing.cpp +++ b/tests/pe/Raytracing.cpp @@ -40,222 +40,6 @@ using namespace walberla::pe::raytracing; typedef std::tuple<Box, Plane, Sphere, Capsule, Ellipsoid> BodyTuple ; -void SphereIntersectsTest() -{ - MaterialID iron = Material::find("iron"); - Sphere sp1(123, 1, Vec3(3,3,3), Quat(), 2, iron, false, true, false); - real_t t; - Vec3 n; - - // ray through the center - Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); - WALBERLA_LOG_INFO("RAY -> SPHERE"); - - WALBERLA_CHECK(intersects(&sp1, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(6)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(-1)); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); - - // ray tangential - Ray ray2(Vec3(3,-5,3), Vec3(0,7.5,real_t(std::sqrt(real_t(15))/real_t(2))).getNormalized()); - WALBERLA_CHECK(intersects(&sp1, ray2, t, n)); - - // sphere behind ray origin - Sphere sp2(123, 1, Vec3(3,-8,3), Quat(), 2, iron, false, true, false); - WALBERLA_CHECK(!intersects(&sp2, ray1, t, n)); - - // sphere around ray origin - Sphere sp3(123, 1, Vec3(3,-5,3), Quat(), 2, iron, false, true, false); - WALBERLA_CHECK(intersects(&sp3, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2)); -} - -void PlaneIntersectsTest() { - MaterialID iron = Material::find("iron"); - // plane with center 3,3,3 and parallel to y-z plane - Plane pl1(1, 1, Vec3(3, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); - - Ray ray1(Vec3(-5,3,3), Vec3(1,0,0)); - real_t t; - Vec3 n; - - WALBERLA_LOG_INFO("RAY -> PLANE"); - WALBERLA_CHECK(intersects(&pl1, ray1, t, n), "ray through center did not hit"); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(8), "distance between ray and plane is incorrect"); - - Ray ray2(Vec3(-5,3,3), Vec3(1,0,-1).getNormalized()); - WALBERLA_CHECK(intersects(&pl1, ray2, t, n), "ray towards random point on plane didn't hit"); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(sqrt(real_t(128))), "distance between ray and plane is incorrect"); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); - - Plane pl1neg(1, 1, Vec3(3, 3, 3), Vec3(-1, 0, 0), real_t(1.0), iron); - WALBERLA_CHECK(intersects(&pl1neg, ray2, t, n), "ray towards random point on plane didn't hit"); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); - - Ray ray3(Vec3(-5,3,3), Vec3(-1,0,0).getNormalized()); - Plane pl5(1, 1, Vec3(-7, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); - WALBERLA_CHECK(intersects(&pl5, ray3, t, n), "ray towards random point on plane didn't hit"); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2), "distance between ray and plane is incorrect"); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); - - // plane with center 3,3,3 and parallel to x-z plane - Plane pl2(1, 1, Vec3(3, 3, 3), Vec3(0, 1, 0), real_t(1.0), iron); - WALBERLA_CHECK(!intersects(&pl2, ray1, t, n), "ray parallel to plane shouldnt hit"); - - // plane with center -10,3,3 and parallel to y-z plane - Plane pl4(1, 1, Vec3(-10, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); - WALBERLA_CHECK(!intersects(&pl4, ray1, t, n), "ray hit plane behind origin"); - - Plane pl6(1, 1, Vec3(3, 3, 0), Vec3(-1, 0, 0), real_t(1.0), iron); - Ray ray4(Vec3(0,0,5), Vec3(1, 0, -1).getNormalized()); - WALBERLA_CHECK(intersects(&pl6, ray4, t, n), "ray didnt hit"); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); -} - -void BoxIntersectsTest() { - WALBERLA_LOG_INFO("RAY -> BOX"); - - MaterialID iron = Material::find("iron"); - real_t t; - Vec3 n; - - Box box1(127, 5, Vec3(0, -15, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); - Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); - WALBERLA_CHECK(!intersects(&box1, ray1, t, n)); - - Box box2(128, 5, Vec3(0, -2, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); - WALBERLA_CHECK(intersects(&box2, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(8), real_t(1e-7)); - - Box box3(128, 5, Vec3(0, 5, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); - WALBERLA_CHECK(intersects(&box3, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(5)); - - Ray ray6(Vec3(-8,5,0), Vec3(1,0,0)); - WALBERLA_CHECK(intersects(&box3, ray6, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(3)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); - - Ray ray7(Vec3(8,5,0), Vec3(-1,0,0)); - WALBERLA_CHECK(intersects(&box3, ray7, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(3)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(1), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); - - // ray origin within box - Ray ray2(Vec3(-2,0,0), Vec3(1,0,1).getNormalized()); - WALBERLA_CHECK(intersects(&box3, ray2, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(7.0710), real_t(1e-4)); - - Ray ray3(Vec3(3,-5,3), Vec3(2, real_t(-1.5), real_t(0.5)).getNormalized()); - Box box4(128, 5, Vec3(0, 8, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); - WALBERLA_CHECK(!intersects(&box4, ray3, t, n)); - - Ray ray4(Vec3(3,-5,3), Vec3(-2, 3, real_t(0.5)).getNormalized()); - WALBERLA_CHECK(intersects(&box4, ray4, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(9.7068), real_t(1e-4)); - - Box box5(128, 5, Vec3(4, 0, 0), Quat(), Vec3(4, 4, 4), iron, false, true, false); - box5.rotate(0,0,math::pi/4); - Ray ray5(Vec3(0,1.5,0), Vec3(1,0,0)); - WALBERLA_CHECK(intersects(&box5, ray5, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(2.67157), real_t(1e-4)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[0], real_t(-0.707107), real_t(1e-5), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[1], real_t(0.707107), real_t(1e-5), "incorrect normal calculated"); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); -} - -void AABBIntersectsTest() { - WALBERLA_LOG_INFO("RAY -> AABB"); - - Ray ray1(Vec3(-5,5,5), Vec3(1,0,0)); - real_t t; - - AABB aabb(0,0,0, - 10,10,10); - - WALBERLA_CHECK(intersects(aabb, ray1, t)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(5)); - - WALBERLA_CHECK(intersects(aabb, ray1, t, 1.0)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); - - Ray ray2(Vec3(-5,5,10.5), Vec3(1,0,0)); // ray shooting over aabb, but within padding passed to intersects - WALBERLA_CHECK(intersects(aabb, ray1, t, 1.0)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); -} - -void CapsuleIntersectsTest() { - MaterialID iron = Material::find("iron"); - real_t t; - Vec3 n; - - Capsule cp1(0, 0, Vec3(2,3,3), Quat(), real_t(2), real_t(2), iron, false, true, false); - - // ray through the center - Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); - WALBERLA_LOG_INFO("RAY -> CAPSULE"); - - WALBERLA_CHECK(intersects(&cp1, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(6)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(-1)); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); - - Ray ray2(Vec3(-5,3,3), Vec3(1,0,0)); - WALBERLA_CHECK(intersects(&cp1, ray2, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1)); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); -} - -void EllipsoidTest() { - WALBERLA_LOG_INFO("RAY -> ELLIPSOID"); - - MaterialID iron = Material::find("iron"); - real_t t; - Vec3 n; - - Ellipsoid el1(0,0, Vec3(2,3,3), Quat(), Vec3(2,3,1), iron, false, true, false); - - Ray ray1(Vec3(-2,3,3), Vec3(1,0,0).getNormalized()); - WALBERLA_CHECK(intersects(&el1, ray1, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1)); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); - - Ray ray2(Vec3(2,3,0), Vec3(0,0,-1).getNormalized()); - WALBERLA_CHECK(!intersects(&el1, ray2, t, n)); - - Ray ray3(Vec3(2,3,5), Vec3(0,0,-1).getNormalized()); - WALBERLA_CHECK(intersects(&el1, ray3, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(1)); - WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); - WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(1)); - - Ray ray4(Vec3(-2,real_t(2),real_t(2)), Vec3(1,real_t(0),real_t(0.5)).getNormalized()); - WALBERLA_CHECK(intersects(&el1, ray4, t, n)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(2.36809), real_t(1e-5)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[0], real_t(-0.78193), real_t(1e-5)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[1], real_t(-0.62324), real_t(1e-5)); - WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[2], real_t(0.012265), real_t(1e-5)); -} - ShadingParameters customBodyToShadingParams(const BodyID body) { if (body->getID() == 10) { return greenShadingParams(body).makeGlossy(30); @@ -335,579 +119,16 @@ void RaytracerTest(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRAC raytracer.generateImage<BodyTuple>(0); } -ShadingParameters customSpheresBodyToShadingParams(const BodyID body) { - if (body->getTypeID() == Plane::getStaticTypeID()) { - return greyShadingParams(body); - } - - switch (body->getID()) { - case 0: - return blueShadingParams(body).makeGlossy(1); - case 1: - return blueShadingParams(body).makeGlossy(10); - case 2: - return blueShadingParams(body).makeGlossy(30); - case 3: - return blueShadingParams(body).makeGlossy(80); - case 4: - return whiteShadingParams(body); - case 5: - return lightGreyShadingParams(body); - case 6: - return greyShadingParams(body); - case 7: - return darkGreyShadingParams(body); - case 8: - return blackShadingParams(body).makeGlossy(100); - case 9: - return redShadingParams(body); - case 10: - return blueShadingParams(body); - case 11: - return violetShadingParams(body); - case 12: - return greenShadingParams(body); - case 13: - return greenShadingParams(body).makeGlossy(30); - case 14: - return blueShadingParams(body).makeGlossy(1000); - default: - return lightGreyShadingParams(body); - } -} - -void RaytracerSpheresTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, walberla::uint8_t antiAliasFactor = 1) { - WALBERLA_LOG_INFO("Raytracer Spheres Scene"); - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,10,10,10), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling( globalBodyStorage, storageID ), "CCD"); - - Lighting lighting(Vec3(0, 5, 8), // 8, 5, 9.5 gut für ebenen, 0,5,8 - Color(1, 1, 1), //diffuse - Color(1, 1, 1), //specular - Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient - Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, - size_t(640), size_t(480), - real_t(49.13), antiAliasFactor, - Vec3(-5,5,5), Vec3(-1,5,5), Vec3(0,0,1), //-5,5,5; -1,5,5 - lighting, - Color(real_t(0.2),real_t(0.2),real_t(0.2)), - customSpheresBodyToShadingParams); - - MaterialID iron = Material::find("iron"); - - createPlane(*globalBodyStorage, 0, Vec3(0,-1,0), Vec3(0,10,0), iron); // left wall - createPlane(*globalBodyStorage, 0, Vec3(0,1,0), Vec3(0,0,0), iron); // right wall - createPlane(*globalBodyStorage, 0, Vec3(0,0,1), Vec3(0,0,0), iron); // floor - createPlane(*globalBodyStorage, 0, Vec3(0,0,-1), Vec3(0,0,10), iron); // ceiling - createPlane(*globalBodyStorage, 0, Vec3(-1,0,0), Vec3(10,0,0), iron); // back wall - createPlane(*globalBodyStorage, 0, Vec3(1,0,0), Vec3(0,0,0), iron); // front wall, should not get rendered - - walberla::id_t id=0; - for (int j=0; j<4; j++) { - for (int i=0; i<4; i++) { - createSphere(*globalBodyStorage, *forest, storageID, id, Vec3(6,real_c(i+1)*real_t(2),real_c(j+1)*real_t(2)), real_t(0.9)); - id++; - } - } - - raytracer.setImageOutputEnabled(true); - - raytracer.setRaytracingAlgorithm(raytracingAlgorithm); - raytracer.generateImage<BodyTuple>(1); -} - -ShadingParameters customHashGridsBodyToShadingParams(const BodyID body) { - if (body->getTypeID() == Sphere::getStaticTypeID()) { - return yellowShadingParams(body); - } - - return defaultBodyTypeDependentShadingParams(body); -} - - -void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, - size_t boxes, size_t capsules, size_t spheres, size_t numberOfViews = 1, - real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2), bool boxRotation = false, - real_t capRadiusMin = real_t(0.1), real_t capRadiusMax = real_t(0.2), real_t capLenMin = real_t(0.1), real_t capLenMax = real_t(0.3), - real_t sphereRadiusMin = real_t(0.1), real_t sphereRadiusMax = real_t(0.3)) { - WALBERLA_LOG_INFO("Generating " << boxes << " boxes, " << capsules << " capsules and " << spheres << " spheres"); - - using namespace walberla::pe::ccd; - WcTimingTree tt; - tt.start("Setup"); - - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(2,3,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); - - const AABB& forestAABB = forest->getDomain(); - - bool removeUnproblematic = false; - std::vector<walberla::id_t> problematicBodyIDs = {165, 5, 31}; //{50, 44, 66, 155, 170, 51}; - std::vector<walberla::id_t> bodySIDs; - - // generate bodies for test - std::vector<BodyID> bodies; - for (size_t i = 0; i < boxes; i++) { - real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 - real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); - real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); - real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); - walberla::id_t id = walberla::id_t(i); - BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), Vec3(len, len, len)); - WALBERLA_CHECK(box_ != nullptr); - if (boxRotation) { - box_->rotate(0, math::realRandom(real_t(0), real_t(1))*math::pi, math::realRandom(real_t(0), real_t(1))*math::pi); - } - bodies.push_back(box_); - bodySIDs.push_back(box_->getSystemID()); - } - - for (size_t i = 0; i < capsules; i++) { - real_t len = math::realRandom(capLenMin, capLenMax); // 0.2 0.5 - real_t radius = math::realRandom(capRadiusMin, capRadiusMax); - real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); - real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); - real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); - walberla::id_t id = walberla::id_t(boxes+i); - CapsuleID capsule = createCapsule(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), radius, len); - WALBERLA_CHECK(capsule != nullptr); - capsule->rotate(0, math::realRandom(real_t(0), real_t(1))*math::pi, math::realRandom(real_t(0), real_t(1))*math::pi); - bodies.push_back(capsule); - bodySIDs.push_back(capsule->getSystemID()); - } - - for (size_t i = 0; i < spheres; i++) { - real_t radius = math::realRandom(sphereRadiusMin, sphereRadiusMax); // 0.2 0.3 - real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); - real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); - real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); - walberla::id_t id = walberla::id_t(boxes+capsules+i); - SphereID sphere = createSphere(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), radius); - WALBERLA_CHECK(sphere != nullptr); - bodies.push_back(sphere); - bodySIDs.push_back(sphere->getSystemID()); - } - - for (auto blockIt = forest->begin(); blockIt != forest->end(); ++blockIt) { - ccd::HashGrids* hashgrids = blockIt->getData<ccd::HashGrids>(ccdID); - hashgrids->update(); - for (auto bodyIt = LocalBodyIterator::begin(*blockIt, storageID); bodyIt != LocalBodyIterator::end(); ++bodyIt) { - if (removeUnproblematic && std::find(problematicBodyIDs.begin(), problematicBodyIDs.end(), bodyIt->getID()) == problematicBodyIDs.end()) { - bodyIt->setPosition(-100, -100, -100); - } - } - } - - MaterialID iron = Material::find("iron"); - createPlane(*globalBodyStorage, 0, Vec3(0,-1,0), Vec3(0,forestAABB.yMax(),0), iron); // left wall - createPlane(*globalBodyStorage, 0, Vec3(0,1,0), Vec3(0,forestAABB.yMin(),0), iron); // right wall - createPlane(*globalBodyStorage, 0, Vec3(0,0,1), Vec3(0,0,forestAABB.zMin()), iron); // floor - createPlane(*globalBodyStorage, 0, Vec3(0,0,-1), Vec3(0,0,forestAABB.zMax()), iron); // ceiling - createPlane(*globalBodyStorage, 0, Vec3(-1,0,0), Vec3(forestAABB.xMax(),0,0), iron); // back wall - createPlane(*globalBodyStorage, 0, Vec3(1,0,0), Vec3(forestAABB.xMin(),0,0), iron); // front wall, should not get rendered - - - std::vector<std::tuple<Vec3, Vec3, Vec3>> viewVectors; - - // y up, in negative z direction - viewVectors.emplace_back(Vec3(2, real_t(2.1), 7), - Vec3(real_t(2.1), 2, 4), - Vec3(0,1,0)); - // y up, in positive z direction - viewVectors.emplace_back(Vec3(2, 2, -3), - Vec3(2, real_t(2.1), real_t(0.1)), - Vec3(0,1,0)); - // x up, in positive z direction - viewVectors.emplace_back(Vec3(2, 2, -3), - Vec3(2, real_t(2.1), real_t(0.1)), - Vec3(1,0,0)); - // y and x up, in positive z direction - viewVectors.emplace_back(Vec3(2, 2, -3), - Vec3(2, real_t(2.1), real_t(0.1)), - Vec3(1,1,0)); - // y and x up, in negative z direction - viewVectors.emplace_back(Vec3(2, 2, 6.5), - Vec3(real_t(2.1), real_t(2.1), 4), - Vec3(real_t(0.5),1,0)); - // z up, in positive x direction - viewVectors.emplace_back(Vec3(-3, 2, real_t(1.9)), - Vec3(0, real_t(2.1), 2), - Vec3(0,0,1)); - // z up, in negative x direction - viewVectors.emplace_back(Vec3(7, 2, real_t(1.9)), - Vec3(4, real_t(2.1), 2), - Vec3(0,0,1)); - // z and y up, in negative x direction - viewVectors.emplace_back(Vec3(7, 2, real_t(1.9)), - Vec3(4, real_t(2.1), 2), - Vec3(0,1,1)); - // z and x up, in negative y direction - viewVectors.emplace_back(Vec3(2, 6, real_t(1.9)), - Vec3(real_t(2.3), 4, 2), - Vec3(1,0,1)); - // z up, in positive y direction - viewVectors.emplace_back(Vec3(2, real_t(-3.6), real_t(1.9)), - Vec3(real_t(2.3), 0, real_t(2.1)), - Vec3(0,0,1)); - - Lighting lighting0(Vec3(forestAABB.xSize()/real_t(2)+1, forestAABB.ySize()/real_t(2), - real_t(2)*forestAABB.zMax()+2), // 8, 5, 9.5 gut für ebenen, 0,5,8 - Color(1, 1, 1), //diffuse - Color(1, 1, 1), //specular - Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient - tt.stop("Setup"); - - size_t i = 0; - for (auto& vector: viewVectors) { - if (i == numberOfViews) { - break; - } - - Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, - size_t(640), size_t(480), - real_t(49.13), antiAliasFactor, - std::get<0>(vector), - std::get<1>(vector), - std::get<2>(vector), - lighting0, - Color(real_t(0.2),real_t(0.2),real_t(0.2)), - customHashGridsBodyToShadingParams); - raytracer.setImageOutputEnabled(true); - raytracer.setFilenameTimestepWidth(12); - WALBERLA_LOG_INFO("output #" << i << " to: " << (boxes*100000000 + capsules*10000 + spheres) << " in " << raytracer.getImageOutputDirectory()); - raytracer.setRaytracingAlgorithm(raytracingAlgorithm); - raytracer.generateImage<BodyTuple>(boxes*100000000 + capsules*10000 + spheres, &tt); - i++; - } - - auto temp = tt.getReduced(); - WALBERLA_ROOT_SECTION() { - std::cout << temp; - } -} - -ShadingParameters customArtifactsBodyToShadingParams(const BodyID body) { - if (body->getTypeID() == Box::getStaticTypeID()) { - return lightGreyShadingParams(body); - } - return defaultShadingParams(body); -} - -void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, - const shared_ptr<BlockStorage> forest, const BlockDataID storageID, - const shared_ptr<BodyStorage> globalBodyStorage, - const BlockDataID ccdID, - const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, - size_t numberOfBoxes, walberla::uint8_t timestepWidth) { - WcTimingTree tt; - - Lighting lighting(cameraPosition, - Color(1, 1, 1), //diffuse - Color(1, 1, 1), //specular - Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient - - Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, - size_t(640), size_t(480), - real_t(49.13), antiAliasFactor, - cameraPosition, - lookAtPoint, - upVector, - lighting, - Color(real_t(0.2),real_t(0.2),real_t(0.2)), - customArtifactsBodyToShadingParams); - raytracer.setImageOutputEnabled(true); - raytracer.setFilenameTimestepWidth(timestepWidth); - raytracer.setRaytracingAlgorithm(raytracingAlgorithm); - WALBERLA_LOG_INFO("output to: " << numberOfBoxes << " in " << raytracer.getImageOutputDirectory()); - raytracer.generateImage<BodyTuple>(numberOfBoxes, &tt); - - auto temp = tt.getReduced(); - WALBERLA_ROOT_SECTION() { - std::cout << temp; - } -} - -void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, - size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { - WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In negative Z direction"); - - WALBERLA_LOG_INFO(" Generating " << boxes << " boxes"); - - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); - - const AABB& forestAABB = forest->getDomain(); - - // generate bodies for test - for (size_t i = 0; i < boxes; i++) { - real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 - real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); - real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); - real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); - if (i%5 == 0) { - x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 1){ - x_min = forestAABB.xMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 2){ - y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 3){ - y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 4){ - z_min = forestAABB.zMin() + math::realRandom(real_t(0), len/real_t(2)); - } - walberla::id_t id = walberla::id_t(i); - BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); - WALBERLA_CHECK(box_ != nullptr); - } - - raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, - forest, storageID, globalBodyStorage, ccdID, - Vec3(2, 2, 7), Vec3(2, 2, 4), Vec3(0,1,0), - boxes, 3); -} - -void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, - size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { - WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive Z direction"); - - WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes"); - - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); - - const AABB& forestAABB = forest->getDomain(); - - // generate bodies for test - std::vector<BodyID> bodies; - for (size_t i = 0; i < boxes; i++) { - real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 - real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); - real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); - real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); - - if (i%5 == 0) { - x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 1){ - x_min = forestAABB.xMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 2){ - y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 3){ - y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 4){ - z_min = forestAABB.zMax() - math::realRandom(len/real_t(2), len); - } - - //real_t z_min = len+0.1; - walberla::id_t id = walberla::id_t(i); - BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); - WALBERLA_CHECK(box_ != nullptr); - } - - raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, - forest, storageID, globalBodyStorage, ccdID, - Vec3(2, 2, -3), Vec3(2, 2, 0), Vec3(0,1,0), - boxes, 4); -} - -void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, - size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { - WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive X direction"); - WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes"); - - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); - - const AABB& forestAABB = forest->getDomain(); - - // generate bodies for test - for (size_t i = 0; i < boxes; i++) { - real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 - real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); - real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); - real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); - - if (i%5 == 0) { - z_min = forestAABB.zMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 1){ - z_min = forestAABB.zMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 2){ - y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); - } else if (i%5 == 3){ - y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); - } else if (i%5 == 4){ - x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); - } - - //real_t z_min = len+0.1; - walberla::id_t id = walberla::id_t(i); - BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); - WALBERLA_CHECK(box_ != nullptr); - } - - raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, - forest, storageID, globalBodyStorage, ccdID, - Vec3(-3, 2, 2), Vec3(0, 2, 2), Vec3(0,0,1), - boxes, 6); -} - - -Vec3 minCornerToGpos(const Vec3& minCorner, real_t lengths) { - return minCorner + Vec3(lengths/2, lengths/2, lengths/2); -} - -void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, walberla::uint8_t antiAliasFactor = 1) { - WALBERLA_LOG_INFO_ON_ROOT("HashGrids Test Scene"); - - shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); - auto forest = blockforest::createBlockForest(AABB(0,0,0,8,8,8), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); - auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); - auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); - - const AABB& forestAABB = forest->getDomain(); - - std::vector<BodyID> bodies; - - // create bodies - size_t id = 0; - real_t len = real_t(0.6); - - real_t x_min = 0, y_min = 0; - len = real_t(1.2); - real_t gap = real_t(0.4); - - // cubes on z = 0 plane - for (int i = 0; ; ++i) { - x_min = forestAABB.xMin() + real_c(i)*(gap+len); - if (x_min > forestAABB.max(0)) { - break; - } - for (int j = 0; ; ++j) { - y_min = forestAABB.yMin() + real_c(j)*(gap+len); - if (y_min > forestAABB.max(1)) { - break; - } - - bodies.push_back(createBox(*globalBodyStorage, *forest, storageID, ++id, minCornerToGpos(Vec3(x_min, y_min, 0), len), Vec3(len, len, len))); - } - } - - //cubes on z = max plane - for (int i = 0; ; ++i) { - x_min = forestAABB.xMin() + real_c(i)*(gap+len); - if (x_min > forestAABB.max(0)) { - break; - } - for (int j = 0; ; ++j) { - y_min = forestAABB.yMin() + real_c(j)*(gap+len); - if (y_min > forestAABB.max(1)) { - break; - } - - bodies.push_back(createBox(*globalBodyStorage, *forest, storageID, ++id, minCornerToGpos(Vec3(x_min, y_min, forestAABB.zMax()-len), len), Vec3(len, len, len))); - } - } - - std::vector<std::tuple<Vec3, Vec3, Vec3>> viewVectors; - - // in negative x direction -> cubes to the right - viewVectors.emplace_back(Vec3(15,4,4), - Vec3(8,4,4), - Vec3(0,1,0)); - // in negative x direction and negative z direction, up vector in y direction -> cubes from the right tilted - viewVectors.emplace_back(Vec3(12,4,8), - Vec3(6,4,2), - Vec3(0,1,0)); - // in negative x direction and negative z direction, up vector in negative y direction - viewVectors.emplace_back(Vec3(12,4,8), - Vec3(6,4,2), - Vec3(0,-1,0)); - // in positive x direction - viewVectors.emplace_back(Vec3(-7,4,4), - Vec3(0,4,4), - Vec3(0,1,0)); - // in negative x direction - viewVectors.emplace_back(Vec3(4,4,15), - Vec3(4,4,8), - Vec3(0,1,0)); - - WcTimingTree tt; - - Lighting lighting(Vec3(1,2,15), - Color(1, 1, 1), //diffuse - Color(1, 1, 1), //specular - Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient - - int i = 0; - for (auto& vector: viewVectors) { - Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, - size_t(640), size_t(480), - real_t(49.13), antiAliasFactor, - std::get<0>(vector), - std::get<1>(vector), - std::get<2>(vector), - lighting, - Color(real_t(0.2),real_t(0.2),real_t(0.2))); - - raytracer.setRaytracingAlgorithm(raytracingAlgorithm); - raytracer.setImageOutputEnabled(true); - raytracer.setFilenameTimestepWidth(1); - WALBERLA_LOG_INFO("output to: " << i << " in " << raytracer.getImageOutputDirectory()); - raytracer.setRaytracingAlgorithm(raytracingAlgorithm); - raytracer.generateImage<BodyTuple>(size_t(i), &tt); - - auto temp = tt.getReduced(); - WALBERLA_ROOT_SECTION() { - std::cout << temp; - } - - i++; - } -} - int main( int argc, char** argv ) { walberla::debug::enterTestMode(); walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); SetBodyTypeIDs<BodyTuple>::execute(); math::seedRandomGenerator( static_cast<unsigned int>(1337 * mpi::MPIManager::instance()->worldRank()) ); - - SphereIntersectsTest(); - PlaneIntersectsTest(); - BoxIntersectsTest(); - AABBIntersectsTest(); - CapsuleIntersectsTest(); - EllipsoidTest(); const Raytracer::Algorithm algorithm = Raytracer::RAYTRACE_COMPARE_BOTH_STRICTLY; const walberla::uint8_t antiAliasFactor = 1; RaytracerTest(algorithm, antiAliasFactor); - RaytracerSpheresTestScene(algorithm, antiAliasFactor); - HashGridsTestScene(algorithm, antiAliasFactor); - - if (argc >= 2 && strcmp(argv[1], "--longrun") == 0) { - HashGridsTest(algorithm, antiAliasFactor, - 50, 30, 130, - 10); - HashGridsTest(algorithm, antiAliasFactor, - 60, 60, 3, - 1, - real_t(0.1), real_t(0.3), true, - real_t(0.1), real_t(0.2), real_t(0.1), real_t(0.2), - real_t(0.5), real_t(0.6)); - HashGridsArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); - HashGridsFromNegativeArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); - HashGridsFromNegativeXArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); - } return EXIT_SUCCESS; } diff --git a/tests/pe/RaytracingHashGrids.cpp b/tests/pe/RaytracingHashGrids.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d2e59c301209a2135bcbff3e9eba22489ddc6b0 --- /dev/null +++ b/tests/pe/RaytracingHashGrids.cpp @@ -0,0 +1,532 @@ +#include <pe/basic.h> +#include "pe/utility/BodyCast.h" + +#include "pe/Materials.h" + +#include "pe/rigidbody/Box.h" +#include "pe/rigidbody/Capsule.h" +#include "pe/rigidbody/Sphere.h" +#include "pe/rigidbody/Plane.h" +#include "pe/rigidbody/Union.h" +#include "pe/rigidbody/Ellipsoid.h" + +#include "pe/rigidbody/SetBodyTypeIDs.h" +#include "pe/Types.h" + +#include "blockforest/Initialization.h" +#include "core/debug/TestSubsystem.h" +#include "core/DataTypes.h" +#include <core/math/Random.h> +#include "core/math/Vector3.h" + +#include <pe/raytracing/Ray.h> +#include <pe/raytracing/Intersects.h> +#include <pe/raytracing/Raytracer.h> +#include <pe/raytracing/Color.h> +#include <pe/raytracing/ShadingFunctions.h> + +#include <pe/ccd/HashGrids.h> +#include "pe/rigidbody/BodyStorage.h" +#include <core/timing/TimingTree.h> + +#include <pe/utility/GetBody.h> + +#include <sstream> +#include <tuple> + +namespace walberla { +using namespace walberla::pe; +using namespace walberla::pe::raytracing; + +typedef std::tuple<Box, Plane, Sphere, Capsule, Ellipsoid> BodyTuple ; + +ShadingParameters customHashGridsBodyToShadingParams(const BodyID body) { + if (body->getTypeID() == Sphere::getStaticTypeID()) { + return yellowShadingParams(body); + } + + return defaultBodyTypeDependentShadingParams(body); +} + + +void HashGridsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, + size_t boxes, size_t capsules, size_t spheres, size_t numberOfViews = 1, + real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2), bool boxRotation = false, + real_t capRadiusMin = real_t(0.1), real_t capRadiusMax = real_t(0.2), real_t capLenMin = real_t(0.1), real_t capLenMax = real_t(0.3), + real_t sphereRadiusMin = real_t(0.1), real_t sphereRadiusMax = real_t(0.3)) { + WALBERLA_LOG_INFO("Generating " << boxes << " boxes, " << capsules << " capsules and " << spheres << " spheres"); + + using namespace walberla::pe::ccd; + WcTimingTree tt; + tt.start("Setup"); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(2,3,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + + const AABB& forestAABB = forest->getDomain(); + + bool removeUnproblematic = false; + std::vector<walberla::id_t> problematicBodyIDs = {165, 5, 31}; //{50, 44, 66, 155, 170, 51}; + std::vector<walberla::id_t> bodySIDs; + + // generate bodies for test + std::vector<BodyID> bodies; + for (size_t i = 0; i < boxes; i++) { + real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 + real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); + real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); + real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); + walberla::id_t id = walberla::id_t(i); + BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), Vec3(len, len, len)); + WALBERLA_CHECK(box_ != nullptr); + if (boxRotation) { + box_->rotate(0, math::realRandom(real_t(0), real_t(1))*math::pi, math::realRandom(real_t(0), real_t(1))*math::pi); + } + bodies.push_back(box_); + bodySIDs.push_back(box_->getSystemID()); + } + + for (size_t i = 0; i < capsules; i++) { + real_t len = math::realRandom(capLenMin, capLenMax); // 0.2 0.5 + real_t radius = math::realRandom(capRadiusMin, capRadiusMax); + real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); + real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); + real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); + walberla::id_t id = walberla::id_t(boxes+i); + CapsuleID capsule = createCapsule(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), radius, len); + WALBERLA_CHECK(capsule != nullptr); + capsule->rotate(0, math::realRandom(real_t(0), real_t(1))*math::pi, math::realRandom(real_t(0), real_t(1))*math::pi); + bodies.push_back(capsule); + bodySIDs.push_back(capsule->getSystemID()); + } + + for (size_t i = 0; i < spheres; i++) { + real_t radius = math::realRandom(sphereRadiusMin, sphereRadiusMax); // 0.2 0.3 + real_t x = math::realRandom(forestAABB.xMin(), forestAABB.xMax()); + real_t y = math::realRandom(forestAABB.yMin(), forestAABB.yMax()); + real_t z = math::realRandom(forestAABB.zMin(), forestAABB.zMax()); + walberla::id_t id = walberla::id_t(boxes+capsules+i); + SphereID sphere = createSphere(*globalBodyStorage, *forest, storageID, id, Vec3(x, y, z), radius); + WALBERLA_CHECK(sphere != nullptr); + bodies.push_back(sphere); + bodySIDs.push_back(sphere->getSystemID()); + } + + for (auto blockIt = forest->begin(); blockIt != forest->end(); ++blockIt) { + ccd::HashGrids* hashgrids = blockIt->getData<ccd::HashGrids>(ccdID); + hashgrids->update(); + for (auto bodyIt = LocalBodyIterator::begin(*blockIt, storageID); bodyIt != LocalBodyIterator::end(); ++bodyIt) { + if (removeUnproblematic && std::find(problematicBodyIDs.begin(), problematicBodyIDs.end(), bodyIt->getID()) == problematicBodyIDs.end()) { + bodyIt->setPosition(-100, -100, -100); + } + } + } + + MaterialID iron = Material::find("iron"); + createPlane(*globalBodyStorage, 0, Vec3(0,-1,0), Vec3(0,forestAABB.yMax(),0), iron); // left wall + createPlane(*globalBodyStorage, 0, Vec3(0,1,0), Vec3(0,forestAABB.yMin(),0), iron); // right wall + createPlane(*globalBodyStorage, 0, Vec3(0,0,1), Vec3(0,0,forestAABB.zMin()), iron); // floor + createPlane(*globalBodyStorage, 0, Vec3(0,0,-1), Vec3(0,0,forestAABB.zMax()), iron); // ceiling + createPlane(*globalBodyStorage, 0, Vec3(-1,0,0), Vec3(forestAABB.xMax(),0,0), iron); // back wall + createPlane(*globalBodyStorage, 0, Vec3(1,0,0), Vec3(forestAABB.xMin(),0,0), iron); // front wall, should not get rendered + + + std::vector<std::tuple<Vec3, Vec3, Vec3>> viewVectors; + + // y up, in negative z direction + viewVectors.emplace_back(Vec3(2, real_t(2.1), 7), + Vec3(real_t(2.1), 2, 4), + Vec3(0,1,0)); + // y up, in positive z direction + viewVectors.emplace_back(Vec3(2, 2, -3), + Vec3(2, real_t(2.1), real_t(0.1)), + Vec3(0,1,0)); + // x up, in positive z direction + viewVectors.emplace_back(Vec3(2, 2, -3), + Vec3(2, real_t(2.1), real_t(0.1)), + Vec3(1,0,0)); + // y and x up, in positive z direction + viewVectors.emplace_back(Vec3(2, 2, -3), + Vec3(2, real_t(2.1), real_t(0.1)), + Vec3(1,1,0)); + // y and x up, in negative z direction + viewVectors.emplace_back(Vec3(2, 2, 6.5), + Vec3(real_t(2.1), real_t(2.1), 4), + Vec3(real_t(0.5),1,0)); + // z up, in positive x direction + viewVectors.emplace_back(Vec3(-3, 2, real_t(1.9)), + Vec3(0, real_t(2.1), 2), + Vec3(0,0,1)); + // z up, in negative x direction + viewVectors.emplace_back(Vec3(7, 2, real_t(1.9)), + Vec3(4, real_t(2.1), 2), + Vec3(0,0,1)); + // z and y up, in negative x direction + viewVectors.emplace_back(Vec3(7, 2, real_t(1.9)), + Vec3(4, real_t(2.1), 2), + Vec3(0,1,1)); + // z and x up, in negative y direction + viewVectors.emplace_back(Vec3(2, 6, real_t(1.9)), + Vec3(real_t(2.3), 4, 2), + Vec3(1,0,1)); + // z up, in positive y direction + viewVectors.emplace_back(Vec3(2, real_t(-3.6), real_t(1.9)), + Vec3(real_t(2.3), 0, real_t(2.1)), + Vec3(0,0,1)); + + Lighting lighting0(Vec3(forestAABB.xSize()/real_t(2)+1, forestAABB.ySize()/real_t(2), + real_t(2)*forestAABB.zMax()+2), // 8, 5, 9.5 gut für ebenen, 0,5,8 + Color(1, 1, 1), //diffuse + Color(1, 1, 1), //specular + Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient + tt.stop("Setup"); + + size_t i = 0; + for (auto& vector: viewVectors) { + if (i == numberOfViews) { + break; + } + + Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, + size_t(640), size_t(480), + real_t(49.13), antiAliasFactor, + std::get<0>(vector), + std::get<1>(vector), + std::get<2>(vector), + lighting0, + Color(real_t(0.2),real_t(0.2),real_t(0.2)), + customHashGridsBodyToShadingParams); + raytracer.setImageOutputEnabled(true); + raytracer.setFilenameTimestepWidth(12); + WALBERLA_LOG_INFO("output #" << i << " to: " << (boxes*100000000 + capsules*10000 + spheres) << " in " << raytracer.getImageOutputDirectory()); + raytracer.setRaytracingAlgorithm(raytracingAlgorithm); + raytracer.generateImage<BodyTuple>(boxes*100000000 + capsules*10000 + spheres, &tt); + i++; + } + + auto temp = tt.getReduced(); + WALBERLA_ROOT_SECTION() { + std::cout << temp; + } +} + +ShadingParameters customArtifactsBodyToShadingParams(const BodyID body) { + if (body->getTypeID() == Box::getStaticTypeID()) { + return lightGreyShadingParams(body); + } + return defaultShadingParams(body); +} + +void raytraceArtifactsForest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, + const shared_ptr<BlockStorage> forest, const BlockDataID storageID, + const shared_ptr<BodyStorage> globalBodyStorage, + const BlockDataID ccdID, + const Vec3& cameraPosition, const Vec3& lookAtPoint, const Vec3& upVector, + size_t numberOfBoxes, walberla::uint8_t timestepWidth) { + WcTimingTree tt; + + Lighting lighting(cameraPosition, + Color(1, 1, 1), //diffuse + Color(1, 1, 1), //specular + Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient + + Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, + size_t(640), size_t(480), + real_t(49.13), antiAliasFactor, + cameraPosition, + lookAtPoint, + upVector, + lighting, + Color(real_t(0.2),real_t(0.2),real_t(0.2)), + customArtifactsBodyToShadingParams); + raytracer.setImageOutputEnabled(true); + raytracer.setFilenameTimestepWidth(timestepWidth); + raytracer.setRaytracingAlgorithm(raytracingAlgorithm); + WALBERLA_LOG_INFO("output to: " << numberOfBoxes << " in " << raytracer.getImageOutputDirectory()); + raytracer.generateImage<BodyTuple>(numberOfBoxes, &tt); + + auto temp = tt.getReduced(); + WALBERLA_ROOT_SECTION() { + std::cout << temp; + } +} + +void HashGridsArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, + size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { + WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In negative Z direction"); + + WALBERLA_LOG_INFO(" Generating " << boxes << " boxes"); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + + const AABB& forestAABB = forest->getDomain(); + + // generate bodies for test + for (size_t i = 0; i < boxes; i++) { + real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 + real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); + real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); + real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); + if (i%5 == 0) { + x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 1){ + x_min = forestAABB.xMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 2){ + y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 3){ + y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 4){ + z_min = forestAABB.zMin() + math::realRandom(real_t(0), len/real_t(2)); + } + walberla::id_t id = walberla::id_t(i); + BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); + WALBERLA_CHECK(box_ != nullptr); + } + + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, + forest, storageID, globalBodyStorage, ccdID, + Vec3(2, 2, 7), Vec3(2, 2, 4), Vec3(0,1,0), + boxes, 3); +} + +void HashGridsFromNegativeArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, + size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { + WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive Z direction"); + + WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes"); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + + const AABB& forestAABB = forest->getDomain(); + + // generate bodies for test + std::vector<BodyID> bodies; + for (size_t i = 0; i < boxes; i++) { + real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 + real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); + real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); + real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); + + if (i%5 == 0) { + x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 1){ + x_min = forestAABB.xMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 2){ + y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 3){ + y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 4){ + z_min = forestAABB.zMax() - math::realRandom(len/real_t(2), len); + } + + //real_t z_min = len+0.1; + walberla::id_t id = walberla::id_t(i); + BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); + WALBERLA_CHECK(box_ != nullptr); + } + + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, + forest, storageID, globalBodyStorage, ccdID, + Vec3(2, 2, -3), Vec3(2, 2, 0), Vec3(0,1,0), + boxes, 4); +} + +void HashGridsFromNegativeXArtifactsTest(Raytracer::Algorithm raytracingAlgorithm, walberla::uint8_t antiAliasFactor, + size_t boxes, real_t boxLenMin = real_t(0.1), real_t boxLenMax = real_t(0.2)) { + WALBERLA_LOG_INFO_ON_ROOT("HashGrids Artifacts Test - In positive X direction"); + WALBERLA_LOG_INFO_ON_ROOT(" Generating " << boxes << " boxes"); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,4,4,4), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + + const AABB& forestAABB = forest->getDomain(); + + // generate bodies for test + for (size_t i = 0; i < boxes; i++) { + real_t len = math::realRandom(boxLenMin, boxLenMax); //0.2 0.5 + real_t x_min = math::realRandom(forestAABB.xMin()+len/real_t(2), forestAABB.xMax()); + real_t y_min = math::realRandom(forestAABB.yMin()+len/real_t(2), forestAABB.yMax()); + real_t z_min = math::realRandom(forestAABB.zMin()+len/real_t(2), forestAABB.zMax()); + + if (i%5 == 0) { + z_min = forestAABB.zMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 1){ + z_min = forestAABB.zMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 2){ + y_min = forestAABB.yMax() - math::realRandom(len/real_t(2), len); + } else if (i%5 == 3){ + y_min = forestAABB.yMin() + math::realRandom(real_t(0), len/real_t(2)); + } else if (i%5 == 4){ + x_min = forestAABB.xMax() - math::realRandom(len/real_t(2), len); + } + + //real_t z_min = len+0.1; + walberla::id_t id = walberla::id_t(i); + BoxID box_ = createBox(*globalBodyStorage, *forest, storageID, id, Vec3(x_min, y_min, z_min), Vec3(len, len, len)); + WALBERLA_CHECK(box_ != nullptr); + } + + raytraceArtifactsForest(raytracingAlgorithm, antiAliasFactor, + forest, storageID, globalBodyStorage, ccdID, + Vec3(-3, 2, 2), Vec3(0, 2, 2), Vec3(0,0,1), + boxes, 6); +} + + +Vec3 minCornerToGpos(const Vec3& minCorner, real_t lengths) { + return minCorner + Vec3(lengths/2, lengths/2, lengths/2); +} + +void HashGridsTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, walberla::uint8_t antiAliasFactor = 1) { + WALBERLA_LOG_INFO_ON_ROOT("HashGrids Test Scene"); + + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,8,8,8), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling(globalBodyStorage, storageID), "CCD"); + + const AABB& forestAABB = forest->getDomain(); + + std::vector<BodyID> bodies; + + // create bodies + size_t id = 0; + real_t len = real_t(0.6); + + real_t x_min = 0, y_min = 0; + len = real_t(1.2); + real_t gap = real_t(0.4); + + // cubes on z = 0 plane + for (int i = 0; ; ++i) { + x_min = forestAABB.xMin() + real_c(i)*(gap+len); + if (x_min > forestAABB.max(0)) { + break; + } + for (int j = 0; ; ++j) { + y_min = forestAABB.yMin() + real_c(j)*(gap+len); + if (y_min > forestAABB.max(1)) { + break; + } + + bodies.push_back(createBox(*globalBodyStorage, *forest, storageID, ++id, minCornerToGpos(Vec3(x_min, y_min, 0), len), Vec3(len, len, len))); + } + } + + //cubes on z = max plane + for (int i = 0; ; ++i) { + x_min = forestAABB.xMin() + real_c(i)*(gap+len); + if (x_min > forestAABB.max(0)) { + break; + } + for (int j = 0; ; ++j) { + y_min = forestAABB.yMin() + real_c(j)*(gap+len); + if (y_min > forestAABB.max(1)) { + break; + } + + bodies.push_back(createBox(*globalBodyStorage, *forest, storageID, ++id, minCornerToGpos(Vec3(x_min, y_min, forestAABB.zMax()-len), len), Vec3(len, len, len))); + } + } + + std::vector<std::tuple<Vec3, Vec3, Vec3>> viewVectors; + + // in negative x direction -> cubes to the right + viewVectors.emplace_back(Vec3(15,4,4), + Vec3(8,4,4), + Vec3(0,1,0)); + // in negative x direction and negative z direction, up vector in y direction -> cubes from the right tilted + viewVectors.emplace_back(Vec3(12,4,8), + Vec3(6,4,2), + Vec3(0,1,0)); + // in negative x direction and negative z direction, up vector in negative y direction + viewVectors.emplace_back(Vec3(12,4,8), + Vec3(6,4,2), + Vec3(0,-1,0)); + // in positive x direction + viewVectors.emplace_back(Vec3(-7,4,4), + Vec3(0,4,4), + Vec3(0,1,0)); + // in negative x direction + viewVectors.emplace_back(Vec3(4,4,15), + Vec3(4,4,8), + Vec3(0,1,0)); + + WcTimingTree tt; + + Lighting lighting(Vec3(1,2,15), + Color(1, 1, 1), //diffuse + Color(1, 1, 1), //specular + Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient + + int i = 0; + for (auto& vector: viewVectors) { + Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, + size_t(640), size_t(480), + real_t(49.13), antiAliasFactor, + std::get<0>(vector), + std::get<1>(vector), + std::get<2>(vector), + lighting, + Color(real_t(0.2),real_t(0.2),real_t(0.2))); + + raytracer.setRaytracingAlgorithm(raytracingAlgorithm); + raytracer.setImageOutputEnabled(true); + raytracer.setFilenameTimestepWidth(1); + WALBERLA_LOG_INFO("output to: " << i << " in " << raytracer.getImageOutputDirectory()); + raytracer.setRaytracingAlgorithm(raytracingAlgorithm); + raytracer.generateImage<BodyTuple>(size_t(i), &tt); + + auto temp = tt.getReduced(); + WALBERLA_ROOT_SECTION() { + std::cout << temp; + } + + i++; + } +} + +int main( int argc, char** argv ) +{ + walberla::debug::enterTestMode(); + walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); + SetBodyTypeIDs<BodyTuple>::execute(); + math::seedRandomGenerator( static_cast<unsigned int>(1337 * mpi::MPIManager::instance()->worldRank()) ); + + const Raytracer::Algorithm algorithm = Raytracer::RAYTRACE_COMPARE_BOTH_STRICTLY; + const walberla::uint8_t antiAliasFactor = 1; + HashGridsTestScene(algorithm, antiAliasFactor); + + if (argc >= 2 && strcmp(argv[1], "--longrun") == 0) { + HashGridsTest(algorithm, antiAliasFactor, + 50, 30, 130, + 10); + HashGridsTest(algorithm, antiAliasFactor, + 60, 60, 3, + 1, + real_t(0.1), real_t(0.3), true, + real_t(0.1), real_t(0.2), real_t(0.1), real_t(0.2), + real_t(0.5), real_t(0.6)); + HashGridsArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); + HashGridsFromNegativeArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); + HashGridsFromNegativeXArtifactsTest(algorithm, antiAliasFactor, 750, real_t(0.2), real_t(0.3)); + } + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main( int argc, char* argv[] ) +{ + return walberla::main( argc, argv ); +} diff --git a/tests/pe/RaytracingIntersection.cpp b/tests/pe/RaytracingIntersection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08b9a980c5193f607ca6aa8f4f36e9b787fbbe13 --- /dev/null +++ b/tests/pe/RaytracingIntersection.cpp @@ -0,0 +1,276 @@ +#include <pe/basic.h> +#include "pe/utility/BodyCast.h" + +#include "pe/Materials.h" + +#include "pe/rigidbody/Box.h" +#include "pe/rigidbody/Capsule.h" +#include "pe/rigidbody/Sphere.h" +#include "pe/rigidbody/Plane.h" +#include "pe/rigidbody/Union.h" +#include "pe/rigidbody/Ellipsoid.h" + +#include "pe/rigidbody/SetBodyTypeIDs.h" +#include "pe/Types.h" + +#include "blockforest/Initialization.h" +#include "core/debug/TestSubsystem.h" +#include "core/DataTypes.h" +#include <core/math/Random.h> +#include "core/math/Vector3.h" + +#include <pe/raytracing/Ray.h> +#include <pe/raytracing/Intersects.h> + +#include "pe/rigidbody/BodyStorage.h" +#include <core/timing/TimingTree.h> + +#include <pe/utility/GetBody.h> + +#include <sstream> +#include <tuple> + +namespace walberla { +using namespace walberla::pe; +using namespace walberla::pe::raytracing; + +typedef std::tuple<Box, Plane, Sphere, Capsule, Ellipsoid> BodyTuple ; + +void SphereIntersectsTest() +{ + MaterialID iron = Material::find("iron"); + Sphere sp1(123, 1, Vec3(3,3,3), Quat(), 2, iron, false, true, false); + real_t t; + Vec3 n; + + // ray through the center + Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); + WALBERLA_LOG_INFO("RAY -> SPHERE"); + + WALBERLA_CHECK(intersects(&sp1, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(6)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(-1)); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); + + // ray tangential + Ray ray2(Vec3(3,-5,3), Vec3(0,7.5,real_t(std::sqrt(real_t(15))/real_t(2))).getNormalized()); + WALBERLA_CHECK(intersects(&sp1, ray2, t, n)); + + // sphere behind ray origin + Sphere sp2(123, 1, Vec3(3,-8,3), Quat(), 2, iron, false, true, false); + WALBERLA_CHECK(!intersects(&sp2, ray1, t, n)); + + // sphere around ray origin + Sphere sp3(123, 1, Vec3(3,-5,3), Quat(), 2, iron, false, true, false); + WALBERLA_CHECK(intersects(&sp3, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2)); +} + +void PlaneIntersectsTest() { + MaterialID iron = Material::find("iron"); + // plane with center 3,3,3 and parallel to y-z plane + Plane pl1(1, 1, Vec3(3, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); + + Ray ray1(Vec3(-5,3,3), Vec3(1,0,0)); + real_t t; + Vec3 n; + + WALBERLA_LOG_INFO("RAY -> PLANE"); + WALBERLA_CHECK(intersects(&pl1, ray1, t, n), "ray through center did not hit"); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(8), "distance between ray and plane is incorrect"); + + Ray ray2(Vec3(-5,3,3), Vec3(1,0,-1).getNormalized()); + WALBERLA_CHECK(intersects(&pl1, ray2, t, n), "ray towards random point on plane didn't hit"); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(sqrt(real_t(128))), "distance between ray and plane is incorrect"); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); + + Plane pl1neg(1, 1, Vec3(3, 3, 3), Vec3(-1, 0, 0), real_t(1.0), iron); + WALBERLA_CHECK(intersects(&pl1neg, ray2, t, n), "ray towards random point on plane didn't hit"); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); + + Ray ray3(Vec3(-5,3,3), Vec3(-1,0,0).getNormalized()); + Plane pl5(1, 1, Vec3(-7, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); + WALBERLA_CHECK(intersects(&pl5, ray3, t, n), "ray towards random point on plane didn't hit"); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2), "distance between ray and plane is incorrect"); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); + + // plane with center 3,3,3 and parallel to x-z plane + Plane pl2(1, 1, Vec3(3, 3, 3), Vec3(0, 1, 0), real_t(1.0), iron); + WALBERLA_CHECK(!intersects(&pl2, ray1, t, n), "ray parallel to plane shouldnt hit"); + + // plane with center -10,3,3 and parallel to y-z plane + Plane pl4(1, 1, Vec3(-10, 3, 3), Vec3(1, 0, 0), real_t(1.0), iron); + WALBERLA_CHECK(!intersects(&pl4, ray1, t, n), "ray hit plane behind origin"); + + Plane pl6(1, 1, Vec3(3, 3, 0), Vec3(-1, 0, 0), real_t(1.0), iron); + Ray ray4(Vec3(0,0,5), Vec3(1, 0, -1).getNormalized()); + WALBERLA_CHECK(intersects(&pl6, ray4, t, n), "ray didnt hit"); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); +} + +void BoxIntersectsTest() { + WALBERLA_LOG_INFO("RAY -> BOX"); + + MaterialID iron = Material::find("iron"); + real_t t; + Vec3 n; + + Box box1(127, 5, Vec3(0, -15, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); + Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); + WALBERLA_CHECK(!intersects(&box1, ray1, t, n)); + + Box box2(128, 5, Vec3(0, -2, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); + WALBERLA_CHECK(intersects(&box2, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(8), real_t(1e-7)); + + Box box3(128, 5, Vec3(0, 5, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); + WALBERLA_CHECK(intersects(&box3, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(5)); + + Ray ray6(Vec3(-8,5,0), Vec3(1,0,0)); + WALBERLA_CHECK(intersects(&box3, ray6, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(3)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); + + Ray ray7(Vec3(8,5,0), Vec3(-1,0,0)); + WALBERLA_CHECK(intersects(&box3, ray7, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(3)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(1), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); + + // ray origin within box + Ray ray2(Vec3(-2,0,0), Vec3(1,0,1).getNormalized()); + WALBERLA_CHECK(intersects(&box3, ray2, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(7.0710), real_t(1e-4)); + + Ray ray3(Vec3(3,-5,3), Vec3(2, real_t(-1.5), real_t(0.5)).getNormalized()); + Box box4(128, 5, Vec3(0, 8, 0), Quat(), Vec3(10, 10, 10), iron, false, true, false); + WALBERLA_CHECK(!intersects(&box4, ray3, t, n)); + + Ray ray4(Vec3(3,-5,3), Vec3(-2, 3, real_t(0.5)).getNormalized()); + WALBERLA_CHECK(intersects(&box4, ray4, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(9.7068), real_t(1e-4)); + + Box box5(128, 5, Vec3(4, 0, 0), Quat(), Vec3(4, 4, 4), iron, false, true, false); + box5.rotate(0,0,math::pi/4); + Ray ray5(Vec3(0,1.5,0), Vec3(1,0,0)); + WALBERLA_CHECK(intersects(&box5, ray5, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(2.67157), real_t(1e-4)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[0], real_t(-0.707107), real_t(1e-5), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[1], real_t(0.707107), real_t(1e-5), "incorrect normal calculated"); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0), "incorrect normal calculated"); +} + +void AABBIntersectsTest() { + WALBERLA_LOG_INFO("RAY -> AABB"); + + Ray ray1(Vec3(-5,5,5), Vec3(1,0,0)); + real_t t; + + AABB aabb(0,0,0, + 10,10,10); + + WALBERLA_CHECK(intersects(aabb, ray1, t)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(5)); + + WALBERLA_CHECK(intersects(aabb, ray1, t, 1.0)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); + + Ray ray2(Vec3(-5,5,10.5), Vec3(1,0,0)); // ray shooting over aabb, but within padding passed to intersects + WALBERLA_CHECK(intersects(aabb, ray1, t, 1.0)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); +} + +void CapsuleIntersectsTest() { + MaterialID iron = Material::find("iron"); + real_t t; + Vec3 n; + + Capsule cp1(0, 0, Vec3(2,3,3), Quat(), real_t(2), real_t(2), iron, false, true, false); + + // ray through the center + Ray ray1(Vec3(3,-5,3), Vec3(0,1,0)); + WALBERLA_LOG_INFO("RAY -> CAPSULE"); + + WALBERLA_CHECK(intersects(&cp1, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(6)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(-1)); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); + + Ray ray2(Vec3(-5,3,3), Vec3(1,0,0)); + WALBERLA_CHECK(intersects(&cp1, ray2, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(4)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1)); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); +} + +void EllipsoidTest() { + WALBERLA_LOG_INFO("RAY -> ELLIPSOID"); + + MaterialID iron = Material::find("iron"); + real_t t; + Vec3 n; + + Ellipsoid el1(0,0, Vec3(2,3,3), Quat(), Vec3(2,3,1), iron, false, true, false); + + Ray ray1(Vec3(-2,3,3), Vec3(1,0,0).getNormalized()); + WALBERLA_CHECK(intersects(&el1, ray1, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(2)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(-1)); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(0)); + + Ray ray2(Vec3(2,3,0), Vec3(0,0,-1).getNormalized()); + WALBERLA_CHECK(!intersects(&el1, ray2, t, n)); + + Ray ray3(Vec3(2,3,5), Vec3(0,0,-1).getNormalized()); + WALBERLA_CHECK(intersects(&el1, ray3, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL(t, real_t(1)); + WALBERLA_CHECK_FLOAT_EQUAL(n[0], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[1], real_t(0)); + WALBERLA_CHECK_FLOAT_EQUAL(n[2], real_t(1)); + + Ray ray4(Vec3(-2,real_t(2),real_t(2)), Vec3(1,real_t(0),real_t(0.5)).getNormalized()); + WALBERLA_CHECK(intersects(&el1, ray4, t, n)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(t, real_t(2.36809), real_t(1e-5)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[0], real_t(-0.78193), real_t(1e-5)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[1], real_t(-0.62324), real_t(1e-5)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(n[2], real_t(0.012265), real_t(1e-5)); +} + +int main( int argc, char** argv ) +{ + walberla::debug::enterTestMode(); + walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); + SetBodyTypeIDs<BodyTuple>::execute(); + math::seedRandomGenerator( static_cast<unsigned int>(1337 * mpi::MPIManager::instance()->worldRank()) ); + + SphereIntersectsTest(); + PlaneIntersectsTest(); + BoxIntersectsTest(); + AABBIntersectsTest(); + CapsuleIntersectsTest(); + EllipsoidTest(); + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main( int argc, char* argv[] ) +{ + return walberla::main( argc, argv ); +} diff --git a/tests/pe/RaytracingSphere.cpp b/tests/pe/RaytracingSphere.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04d1d6f7b95e34f754a735d31cab017d26243c18 --- /dev/null +++ b/tests/pe/RaytracingSphere.cpp @@ -0,0 +1,144 @@ +#include <pe/basic.h> +#include "pe/utility/BodyCast.h" + +#include "pe/Materials.h" + +#include "pe/rigidbody/Box.h" +#include "pe/rigidbody/Capsule.h" +#include "pe/rigidbody/Sphere.h" +#include "pe/rigidbody/Plane.h" +#include "pe/rigidbody/Union.h" +#include "pe/rigidbody/Ellipsoid.h" + +#include "pe/rigidbody/SetBodyTypeIDs.h" +#include "pe/Types.h" + +#include "blockforest/Initialization.h" +#include "core/debug/TestSubsystem.h" +#include "core/DataTypes.h" +#include <core/math/Random.h> +#include "core/math/Vector3.h" + +#include <pe/raytracing/Ray.h> +#include <pe/raytracing/Intersects.h> +#include <pe/raytracing/Raytracer.h> +#include <pe/raytracing/Color.h> +#include <pe/raytracing/ShadingFunctions.h> + +#include <pe/ccd/HashGrids.h> +#include "pe/rigidbody/BodyStorage.h" +#include <core/timing/TimingTree.h> + +#include <pe/utility/GetBody.h> + +#include <sstream> +#include <tuple> + +namespace walberla { +using namespace walberla::pe; +using namespace walberla::pe::raytracing; + +typedef std::tuple<Box, Plane, Sphere, Capsule, Ellipsoid> BodyTuple ; + +ShadingParameters customSpheresBodyToShadingParams(const BodyID body) { + if (body->getTypeID() == Plane::getStaticTypeID()) { + return greyShadingParams(body); + } + + switch (body->getID()) { + case 0: + return blueShadingParams(body).makeGlossy(1); + case 1: + return blueShadingParams(body).makeGlossy(10); + case 2: + return blueShadingParams(body).makeGlossy(30); + case 3: + return blueShadingParams(body).makeGlossy(80); + case 4: + return whiteShadingParams(body); + case 5: + return lightGreyShadingParams(body); + case 6: + return greyShadingParams(body); + case 7: + return darkGreyShadingParams(body); + case 8: + return blackShadingParams(body).makeGlossy(100); + case 9: + return redShadingParams(body); + case 10: + return blueShadingParams(body); + case 11: + return violetShadingParams(body); + case 12: + return greenShadingParams(body); + case 13: + return greenShadingParams(body).makeGlossy(30); + case 14: + return blueShadingParams(body).makeGlossy(1000); + default: + return lightGreyShadingParams(body); + } +} + +void RaytracerSpheresTestScene(Raytracer::Algorithm raytracingAlgorithm = Raytracer::RAYTRACE_HASHGRIDS, walberla::uint8_t antiAliasFactor = 1) { + WALBERLA_LOG_INFO("Raytracer Spheres Scene"); + shared_ptr<BodyStorage> globalBodyStorage = make_shared<BodyStorage>(); + auto forest = blockforest::createBlockForest(AABB(0,0,0,10,10,10), Vector3<uint_t>(1,1,1), Vector3<bool>(false, false, false)); + auto storageID = forest->addBlockData(createStorageDataHandling<BodyTuple>(), "Storage"); + auto ccdID = forest->addBlockData(ccd::createHashGridsDataHandling( globalBodyStorage, storageID ), "CCD"); + + Lighting lighting(Vec3(0, 5, 8), // 8, 5, 9.5 gut für ebenen, 0,5,8 + Color(1, 1, 1), //diffuse + Color(1, 1, 1), //specular + Color(real_t(0.4), real_t(0.4), real_t(0.4))); //ambient + Raytracer raytracer(forest, storageID, globalBodyStorage, ccdID, + size_t(640), size_t(480), + real_t(49.13), antiAliasFactor, + Vec3(-5,5,5), Vec3(-1,5,5), Vec3(0,0,1), //-5,5,5; -1,5,5 + lighting, + Color(real_t(0.2),real_t(0.2),real_t(0.2)), + customSpheresBodyToShadingParams); + + MaterialID iron = Material::find("iron"); + + createPlane(*globalBodyStorage, 0, Vec3(0,-1,0), Vec3(0,10,0), iron); // left wall + createPlane(*globalBodyStorage, 0, Vec3(0,1,0), Vec3(0,0,0), iron); // right wall + createPlane(*globalBodyStorage, 0, Vec3(0,0,1), Vec3(0,0,0), iron); // floor + createPlane(*globalBodyStorage, 0, Vec3(0,0,-1), Vec3(0,0,10), iron); // ceiling + createPlane(*globalBodyStorage, 0, Vec3(-1,0,0), Vec3(10,0,0), iron); // back wall + createPlane(*globalBodyStorage, 0, Vec3(1,0,0), Vec3(0,0,0), iron); // front wall, should not get rendered + + walberla::id_t id=0; + for (int j=0; j<4; j++) { + for (int i=0; i<4; i++) { + createSphere(*globalBodyStorage, *forest, storageID, id, Vec3(6,real_c(i+1)*real_t(2),real_c(j+1)*real_t(2)), real_t(0.9)); + id++; + } + } + + raytracer.setImageOutputEnabled(true); + + raytracer.setRaytracingAlgorithm(raytracingAlgorithm); + raytracer.generateImage<BodyTuple>(1); +} + +int main( int argc, char** argv ) +{ + walberla::debug::enterTestMode(); + walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); + SetBodyTypeIDs<BodyTuple>::execute(); + math::seedRandomGenerator( static_cast<unsigned int>(1337 * mpi::MPIManager::instance()->worldRank()) ); + + const Raytracer::Algorithm algorithm = Raytracer::RAYTRACE_COMPARE_BOTH_STRICTLY; + const walberla::uint8_t antiAliasFactor = 1; + RaytracerSpheresTestScene(algorithm, antiAliasFactor); + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main( int argc, char* argv[] ) +{ + return walberla::main( argc, argv ); +}