diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-03-05 01:59:16 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2023-03-05 01:59:16 +0000 |
commit | d4c073a18adaed73973f34c6c39fc15664d9211d (patch) | |
tree | 44536af3af0284ab75eae79ef81a5e4452019269 /test | |
parent | Add helper operator to perform vec3*mat4 and perspective divide (diff) | |
parent | Remove old hard coded asset factory test, run entirely from XML load and rend... (diff) | |
download | ilt-d4c073a18adaed73973f34c6c39fc15664d9211d.tar.bz2 ilt-d4c073a18adaed73973f34c6c39fc15664d9211d.tar.xz ilt-d4c073a18adaed73973f34c6c39fc15664d9211d.zip |
Merge branch 'model-factory'
Diffstat (limited to 'test')
23 files changed, 240 insertions, 47 deletions
diff --git a/test/Jamfile.jam b/test/Jamfile.jam index cefad7b..907632e 100644 --- a/test/Jamfile.jam +++ b/test/Jamfile.jam @@ -2,6 +2,7 @@ import testing ; import sequence ; lib boost_unit_test_framework ; +lib benchmark ; path-constant res : ../res ; path-constant fixtures : fixtures ; @@ -39,7 +40,7 @@ project : requirements <toolset>tidy:<xcheckxx>hicpp-vararg <toolset>tidy:<librarydef>boost ; -lib test : [ glob *.cpp : test-*.cpp ] ; +lib test : [ glob *.cpp : test-*.cpp perf-*.cpp ] ; run test-collection.cpp ; run test-obj.cpp ; @@ -52,5 +53,8 @@ run test-text.cpp ; run test-enumDetails.cpp ; run test-render.cpp : : : <library>test ; run test-glContextBhvr.cpp ; +run test-assetFactory.cpp : -- : ../res/brush47.xml : <library>test ; +run perf-assetFactory.cpp : : : <library>benchmark <library>test ; compile test-static-enumDetails.cpp ; compile test-static-stream_support.cpp ; +explicit perf-assetFactory ; diff --git a/test/fixtures/json/abs.json b/test/fixtures/json/abs.json index 8492df3..1b489ef 100644 --- a/test/fixtures/json/abs.json +++ b/test/fixtures/json/abs.json @@ -1,6 +1,6 @@ { "aptr": { - "@typeid": "SubObject", + "p.typeid": "SubObject", "base": "set base", "sub": "set sub" } diff --git a/test/fixtures/json/bad/empty_abs.json b/test/fixtures/json/bad/empty_abs.json index 7d22001..5cc3598 100644 --- a/test/fixtures/json/bad/empty_abs.json +++ b/test/fixtures/json/bad/empty_abs.json @@ -1,5 +1,5 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 1, "aptr": {}, "str": "after" diff --git a/test/fixtures/json/bad/implicit_abs.json b/test/fixtures/json/bad/implicit_abs.json index 573b323..bf81ee4 100644 --- a/test/fixtures/json/bad/implicit_abs.json +++ b/test/fixtures/json/bad/implicit_abs.json @@ -1,5 +1,5 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 1, "aptr": { "str": "trigger" diff --git a/test/fixtures/json/bad/late_type.json b/test/fixtures/json/bad/late_type.json index 171575a..d1d6f6c 100644 --- a/test/fixtures/json/bad/late_type.json +++ b/test/fixtures/json/bad/late_type.json @@ -1,4 +1,4 @@ { "str": "trigger", - "@typeid": "doesn't matter" + "p.typeid": "doesn't matter" } diff --git a/test/fixtures/json/bad/wrong_type.json b/test/fixtures/json/bad/wrong_type.json index 777d791..4f19033 100644 --- a/test/fixtures/json/bad/wrong_type.json +++ b/test/fixtures/json/bad/wrong_type.json @@ -1,5 +1,5 @@ { "ptr": { - "@typeid": "SubObject" + "p.typeid": "SubObject" } } diff --git a/test/fixtures/json/bad_type.json b/test/fixtures/json/bad_type.json index f316bd1..70b9d1a 100644 --- a/test/fixtures/json/bad_type.json +++ b/test/fixtures/json/bad_type.json @@ -1,3 +1,3 @@ { - "@typeid": "no such type" + "p.typeid": "no such type" } diff --git a/test/fixtures/json/conv.json b/test/fixtures/json/conv.json new file mode 100644 index 0000000..1b690d5 --- /dev/null +++ b/test/fixtures/json/conv.json @@ -0,0 +1,4 @@ +{ + "bl": "true", + "flt": "3.14" +} diff --git a/test/fixtures/json/empty.json b/test/fixtures/json/empty.json index a9193a3..9575565 100644 --- a/test/fixtures/json/empty.json +++ b/test/fixtures/json/empty.json @@ -1,5 +1,5 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 1, "ptr": {}, "str": "after" diff --git a/test/fixtures/json/implicit.json b/test/fixtures/json/implicit.json index 478cec6..6efc2ba 100644 --- a/test/fixtures/json/implicit.json +++ b/test/fixtures/json/implicit.json @@ -1,5 +1,5 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 1, "ptr": { "str": "trigger", diff --git a/test/fixtures/json/load_object.json b/test/fixtures/json/load_object.json index bb32298..c622885 100644 --- a/test/fixtures/json/load_object.json +++ b/test/fixtures/json/load_object.json @@ -1,5 +1,5 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 3.14, "str": "Lovely string", "bl": true, @@ -48,7 +48,7 @@ [] ], "ptr": { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 3.14, "str": "Lovely string" } diff --git a/test/fixtures/json/nested.json b/test/fixtures/json/nested.json index 98951fc..1e271e3 100644 --- a/test/fixtures/json/nested.json +++ b/test/fixtures/json/nested.json @@ -1,14 +1,14 @@ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 1, "ptr": { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 2, "ptr": { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 3, "ptr": { - "@typeid": "TestObject", + "p.typeid": "TestObject", "flt": 4, "ptr": null, "str": "four" diff --git a/test/fixtures/json/shared_ptr_diff.json b/test/fixtures/json/shared_ptr_diff.json index bb18e33..043be4a 100644 --- a/test/fixtures/json/shared_ptr_diff.json +++ b/test/fixtures/json/shared_ptr_diff.json @@ -1,11 +1,11 @@ { - "@typeid": "SharedTestObject", + "p.typeid": "SharedTestObject", "sptr": { - "@typeid": "SubObject", - "@id": "someid" + "p.typeid": "SubObject", + "p.id": "someid" }, "ssptr": { - "@typeid": "SubObject", - "@id": "some other id" + "p.typeid": "SubObject", + "p.id": "some other id" } } diff --git a/test/fixtures/json/shared_ptr_diff_default.json b/test/fixtures/json/shared_ptr_diff_default.json index 69f5e85..c78bc12 100644 --- a/test/fixtures/json/shared_ptr_diff_default.json +++ b/test/fixtures/json/shared_ptr_diff_default.json @@ -1,8 +1,8 @@ { - "@typeid": "SharedTestObject", + "p.typeid": "SharedTestObject", "sptr": { - "@typeid": "SubObject", - "@id": "someid" + "p.typeid": "SubObject", + "p.id": "someid" }, "ssptr": {} } diff --git a/test/fixtures/json/shared_ptr_null.json b/test/fixtures/json/shared_ptr_null.json index c2461e8..8669bf2 100644 --- a/test/fixtures/json/shared_ptr_null.json +++ b/test/fixtures/json/shared_ptr_null.json @@ -1,8 +1,8 @@ { - "@typeid": "SharedTestObject", + "p.typeid": "SharedTestObject", "sptr": { - "@typeid": "SubObject", - "@id": "someid" + "p.typeid": "SubObject", + "p.id": "someid" }, "ssptr": null } diff --git a/test/fixtures/json/shared_ptr_same.json b/test/fixtures/json/shared_ptr_same.json index 4115493..2838e82 100644 --- a/test/fixtures/json/shared_ptr_same.json +++ b/test/fixtures/json/shared_ptr_same.json @@ -1,8 +1,8 @@ { - "@typeid": "SharedTestObject", + "p.typeid": "SharedTestObject", "sptr": { - "@typeid": "SubObject", - "@id": "someid" + "p.typeid": "SubObject", + "p.id": "someid" }, "ssptr": "someid" } diff --git a/test/fixtures/json/shared_ptr_wrong_type.json b/test/fixtures/json/shared_ptr_wrong_type.json index 68f7533..5d4e655 100644 --- a/test/fixtures/json/shared_ptr_wrong_type.json +++ b/test/fixtures/json/shared_ptr_wrong_type.json @@ -1,8 +1,8 @@ { - "@typeid": "SharedTestObject", + "p.typeid": "SharedTestObject", "sptr": { - "@typeid": "SubObject2", - "@id": "someid" + "p.typeid": "SubObject2", + "p.id": "someid" }, "ssptr": "someid" } diff --git a/test/fixtures/json/vector_ptr.json b/test/fixtures/json/vector_ptr.json index 8a07a2e..654bd6c 100644 --- a/test/fixtures/json/vector_ptr.json +++ b/test/fixtures/json/vector_ptr.json @@ -1,7 +1,7 @@ { "vptr": [ { - "@typeid": "TestObject", + "p.typeid": "TestObject", "str": "type" }, { diff --git a/test/fixtures/rgb.txt b/test/fixtures/rgb.txt new file mode 100644 index 0000000..2fab7af --- /dev/null +++ b/test/fixtures/rgb.txt @@ -0,0 +1,20 @@ +127 255 0 chartreuse1 +190 190 190 x11 gray +169 169 169 DarkGrey + 0 255 255 cyan +173 173 173 gray68 +202 225 255 LightSteelBlue1 + 72 209 204 medium turquoise +224 238 224 honeydew2 +238 197 145 burlywood2 +205 133 63 peru + 28 28 28 gray11 + 83 134 139 CadetBlue4 +139 76 57 salmon4 +238 232 170 pale goldenrod +112 128 144 slate grey +255 255 0 yellow1 +159 121 238 MediumPurple2 +190 190 190 gray + 66 66 66 grey26 +0 0 139 DarkBlue diff --git a/test/perf-assetFactory.cpp b/test/perf-assetFactory.cpp new file mode 100644 index 0000000..f702fe7 --- /dev/null +++ b/test/perf-assetFactory.cpp @@ -0,0 +1,32 @@ +#include "assetFactory/assetFactory.h" +#include "assetFactory/factoryMesh.h" +#include "testMainWindow.h" +#include "ui/applicationBase.h" +#include <benchmark/benchmark.h> + +static void +brush47xml_load(benchmark::State & state) +{ + for (auto _ : state) { + benchmark::DoNotOptimize(AssetFactory::loadXML(RESDIR "/brush47.xml")); + } +} + +static void +brush47xml_mesh(benchmark::State & state) +{ + TestMainWindow window; + + const auto mf = AssetFactory::loadXML(RESDIR "/brush47.xml"); + const auto brush47 = mf->assets.at("brush-47"); + for (auto _ : state) { + std::for_each(brush47->meshes.begin(), brush47->meshes.end(), [](const FactoryMesh::CPtr & factoryMesh) { + factoryMesh->createMesh(); + }); + } +} + +BENCHMARK(brush47xml_load); +BENCHMARK(brush47xml_mesh); + +BENCHMARK_MAIN(); diff --git a/test/test-assetFactory.cpp b/test/test-assetFactory.cpp new file mode 100644 index 0000000..ae5a88a --- /dev/null +++ b/test/test-assetFactory.cpp @@ -0,0 +1,127 @@ +#define BOOST_TEST_MODULE test_asset_factory + +#include "testHelpers.h" +#include "testRenderOutput.h" +#include <boost/test/data/test_case.hpp> +#include <boost/test/unit_test.hpp> + +#include "assetFactory/assetFactory.h" +#include "assetFactory/object.h" +#include "game/vehicles/railVehicle.h" +#include "game/vehicles/railVehicleClass.h" +#include "gfx/gl/sceneRenderer.h" +#include "gfx/renderable.h" +#include "lib/collection.hpp" +#include "lib/location.hpp" +#include "lib/stream_support.hpp" +#include "testMainWindow.h" +#include "ui/applicationBase.h" + +BOOST_GLOBAL_FIXTURE(ApplicationBase); +BOOST_GLOBAL_FIXTURE(TestMainWindow); + +const std::filesystem::path TMP {"/tmp"}; +class FactoryFixture : public TestRenderOutputSize<glm::ivec2 {2048, 2048}>, public SceneProvider { +public: + FactoryFixture() : sceneRenderer {size, output} { } + ~FactoryFixture() + { + glDisable(GL_DEBUG_OUTPUT); + auto outpath = (TMP / boost::unit_test::framework::current_test_case().full_name()).replace_extension(".tga"); + std::filesystem::create_directories(outpath.parent_path()); + Texture::save(outImage, size, outpath.c_str()); + } + void + content(const SceneShader & shader) const override + { + shader.basic.use(Location {{0, 0, 0}, {0, 0, 0}}); + objects.apply(&Renderable::render, shader); + } + void + lights(const SceneShader & shader) const override + { + shader.pointLight.add({-3, 1, 5}, {1, 1, 1}, .1F); + } + void + environment(const SceneShader &, const SceneRenderer & sceneRenderer) const override + { + sceneRenderer.setAmbientLight({.2, .2, .2}); + sceneRenderer.setDirectionalLight({.3, .3, .3}, east + south + south + down, *this); + } + void + shadows(const ShadowMapper & mapper) const override + { + mapper.dynamicPoint.use(Location {{0, 0, 0}, {0, 0, 0}}); + objects.apply(&Renderable::shadows, mapper); + } + void + render(float dist = 10.f) + { + sceneRenderer.camera.setView({dist, dist, dist}, south + west + down); + sceneRenderer.render(*this); + } + Collection<const Renderable> objects; + +private: + SceneRenderer sceneRenderer; +}; + +BOOST_FIXTURE_TEST_SUITE(m, FactoryFixture); +BOOST_AUTO_TEST_CASE(brush47xml) +{ + auto mf = AssetFactory::loadXML(RESDIR "/brush47.xml"); + BOOST_REQUIRE(mf); + BOOST_REQUIRE_EQUAL(6, mf->shapes.size()); + BOOST_CHECK(mf->shapes.at("plane")); + BOOST_CHECK(mf->shapes.at("cylinder")); + BOOST_CHECK(mf->shapes.at("cuboid")); + BOOST_CHECK(mf->shapes.at("wheel")); + BOOST_CHECK(mf->shapes.at("axel")); + auto bogie = mf->shapes.at("bogie"); + BOOST_REQUIRE(bogie); + auto bogieObj = std::dynamic_pointer_cast<const Object>(bogie); + BOOST_CHECK_EQUAL(3, bogieObj->uses.size()); + BOOST_CHECK_EQUAL(1, mf->assets.size()); + auto brush47 = mf->assets.at("brush-47"); + BOOST_REQUIRE(brush47); + auto brush47rvc = std::dynamic_pointer_cast<RailVehicleClass>(brush47); + BOOST_REQUIRE(brush47rvc); + BOOST_REQUIRE(brush47rvc->bodyMesh); + BOOST_REQUIRE(brush47rvc->bogies.front()); + BOOST_REQUIRE(brush47rvc->bogies.back()); + + auto railVehicle = std::make_shared<RailVehicle>(brush47rvc); + objects.objects.push_back(railVehicle); + + render(20); +} +BOOST_AUTO_TEST_SUITE_END(); + +template<typename T> using InOut = std::tuple<T, T>; +BOOST_DATA_TEST_CASE(normalizeColourName, + boost::unit_test::data::make<InOut<std::string>>({ + {"", ""}, + {"black", "black"}, + {" black ", "black"}, + {" b l a c k ", "black"}, + {" B L A c k ", "black"}, + {"BLAck ", "black"}, + {"BLACK ", "black"}, + {"BlAck ", "black"}, + {"Bl Ack ", "black"}, + }), + in_, exp) +{ + auto in {in_}; + BOOST_CHECK_NO_THROW(AssetFactory::normalizeColourName(in)); + BOOST_CHECK_EQUAL(in, exp); +} + +BOOST_AUTO_TEST_CASE(parseX11RGB) +{ + const auto parsedColours = AssetFactory::parseX11RGB(FIXTURESDIR "rgb.txt"); + BOOST_REQUIRE_EQUAL(parsedColours.size(), 20); + BOOST_CHECK_CLOSE_VEC(parsedColours.at("cyan"), AssetFactory::Colour(0, 1, 1)); + BOOST_CHECK_CLOSE_VEC(parsedColours.at("slategrey"), AssetFactory::Colour(0.44F, 0.5, 0.56F)); + BOOST_CHECK_CLOSE_VEC(parsedColours.at("lightsteelblue1"), AssetFactory::Colour(0.79, 0.88, 1)); +} diff --git a/test/test-persistence.cpp b/test/test-persistence.cpp index e13cb7a..7bca91a 100644 --- a/test/test-persistence.cpp +++ b/test/test-persistence.cpp @@ -83,16 +83,14 @@ struct TestObject : public Persistence::Persistable { } }; -struct JPP : public Persistence::JsonParsePersistence { +struct JPP { template<typename T> T load_json(const std::filesystem::path & path) { BOOST_TEST_CONTEXT(path) { std::ifstream ss {path}; - auto to = loadState<T>(ss); - Persistence::sharedObjects.clear(); - BOOST_CHECK(stk.empty()); + auto to = Persistence::JsonParsePersistence {}.loadState<T>(ss); BOOST_REQUIRE(to); return to; } @@ -208,6 +206,14 @@ BOOST_FIXTURE_TEST_CASE(load_vector_ptr, JPP) BOOST_CHECK(to->vptr.at(3)->str.empty()); } +BOOST_FIXTURE_TEST_CASE(test_conversion, JPP) +{ + auto to = load_json<std::unique_ptr<TestObject>>(FIXTURESDIR "json/conv.json"); + BOOST_REQUIRE(to); + BOOST_CHECK_EQUAL(to->bl, true); + BOOST_CHECK_EQUAL(to->flt, 3.14F); +} + struct SharedTestObject : public Persistence::Persistable { SharedTestObject() = default; @@ -281,10 +287,10 @@ auto const TEST_STRINGS_DECODE_ONLY = boost::unit_test::data::make<svs>({ {R"J("\u056b ARMENIAN SMALL LETTER INI")J", "ի ARMENIAN SMALL LETTER INI"}, {R"J("\u0833 SAMARITAN PUNCTUATION BAU")J", "࠳ SAMARITAN PUNCTUATION BAU"}, }); -BOOST_DATA_TEST_CASE_F(JPP, load_strings, TEST_STRINGS + TEST_STRINGS_DECODE_ONLY, in, exp) +BOOST_DATA_TEST_CASE(load_strings, TEST_STRINGS + TEST_STRINGS_DECODE_ONLY, in, exp) { std::stringstream str {in}; - BOOST_CHECK_EQUAL(loadState<std::string>(str), exp); + BOOST_CHECK_EQUAL(Persistence::JsonParsePersistence {}.loadState<std::string>(str), exp); } using cpstr = std::tuple<unsigned long, std::string_view>; @@ -320,7 +326,7 @@ BOOST_AUTO_TEST_CASE(write_test_dfl) std::stringstream ss; Persistence::JsonWritePersistence {ss}.saveState(to); BOOST_CHECK_EQUAL(ss.str(), - R"({"@typeid":"TestObject","flt":0,"str":"","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"vptr":[]})"); + R"({"p.typeid":"TestObject","flt":0,"str":"","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"vptr":[]})"); } BOOST_FIXTURE_TEST_CASE(write_test_loaded, JPP) @@ -329,7 +335,7 @@ BOOST_FIXTURE_TEST_CASE(write_test_loaded, JPP) std::stringstream ss; Persistence::JsonWritePersistence {ss}.saveState(to); BOOST_CHECK_EQUAL(ss.str(), - R"({"@typeid":"TestObject","flt":3.14,"str":"Lovely string","bl":true,"pos":[3.14,6.28,1.57],"flts":[3.14,6.28,1.57,0,-1,-3.14],"poss":[[3.14,6.28,1.57],[0,-1,-3.14]],"nest":[[["a","b"],["c","d","e"]],[["f"]],[]],"ptr":{"@typeid":"TestObject","flt":3.14,"str":"Lovely string","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"vptr":[]},"vptr":[]})"); + R"({"p.typeid":"TestObject","flt":3.14,"str":"Lovely string","bl":true,"pos":[3.14,6.28,1.57],"flts":[3.14,6.28,1.57,0,-1,-3.14],"poss":[[3.14,6.28,1.57],[0,-1,-3.14]],"nest":[[["a","b"],["c","d","e"]],[["f"]],[]],"ptr":{"p.typeid":"TestObject","flt":3.14,"str":"Lovely string","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"vptr":[]},"vptr":[]})"); } BOOST_FIXTURE_TEST_CASE(write_test_loaded_abs, JPP) @@ -338,7 +344,7 @@ BOOST_FIXTURE_TEST_CASE(write_test_loaded_abs, JPP) std::stringstream ss; Persistence::JsonWritePersistence {ss}.saveState(to); BOOST_CHECK_EQUAL(ss.str(), - R"({"@typeid":"TestObject","flt":0,"str":"","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"aptr":{"@typeid":"SubObject","base":"set base","sub":"set sub"},"vptr":[]})"); + R"({"p.typeid":"TestObject","flt":0,"str":"","bl":false,"pos":[0,0,0],"flts":[],"poss":[],"nest":[],"aptr":{"p.typeid":"SubObject","base":"set base","sub":"set sub"},"vptr":[]})"); } BOOST_FIXTURE_TEST_CASE(write_test_loaded_shared, JPP) @@ -349,7 +355,7 @@ BOOST_FIXTURE_TEST_CASE(write_test_loaded_shared, JPP) Persistence::JsonWritePersistence {ss}.saveState(to); BOOST_CHECK_EQUAL(Persistence::seenSharedObjects.size(), 1); BOOST_CHECK_EQUAL(ss.str(), - R"({"@typeid":"SharedTestObject","sptr":{"@typeid":"SubObject","@id":"someid","base":"","sub":""},"ssptr":"someid"})"); + R"({"p.typeid":"SharedTestObject","sptr":{"p.typeid":"SubObject","p.id":"someid","base":"","sub":""},"ssptr":"someid"})"); } BOOST_DATA_TEST_CASE(write_special_strings, TEST_STRINGS, exp, in) diff --git a/test/test-render.cpp b/test/test-render.cpp index 7db847d..7771760 100644 --- a/test/test-render.cpp +++ b/test/test-render.cpp @@ -29,8 +29,8 @@ class TestScene : public SceneProvider { content(const SceneShader & shader) const override { terrain.render(shader); - train.render(shader, Location {{52, 50, 2}}, {Location {}, Location {}}); - train.render(shader, Location {{52, 30, 2}}, {Location {}, Location {}}); + train.render(shader, Location {{52, 50, 2}}, {Location {{52, 56, 2}}, Location {{52, 44, 2}}}); + train.render(shader, Location {{52, 30, 2}}, {Location {{52, 36, 2}}, Location {{52, 24, 2}}}); } void lights(const SceneShader &) const override @@ -40,8 +40,8 @@ class TestScene : public SceneProvider { shadows(const ShadowMapper & shadowMapper) const override { terrain.shadows(shadowMapper); - train.shadows(shadowMapper, Location {{52, 50, 2}}); - train.shadows(shadowMapper, Location {{52, 30, 2}}); + train.shadows(shadowMapper, Location {{52, 50, 2}}, {Location {{52, 56, 2}}, Location {{52, 44, 2}}}); + train.shadows(shadowMapper, Location {{52, 30, 2}}, {Location {{52, 36, 2}}, Location {{52, 24, 2}}}); } }; |