/*! Checks whether a single layout object shape will fit into one of the childrens quadTree. It calls add() and returns success if the new layout object fits entirely into one of the possible subtrees or if it blows up its overlaping area not more than 10%. Returns false if the shape does not fit anywhere - means it should be placed higher into the quadTree structure.\n The method might be called recursively via the add() method. */ bool laydata::quadTree::fitintree(tdtdata* shape) { DBbox shovl = shape->overlap(); float clipedarea[4]; // check the clipping to see in witch region to place the shape for (byte i = 0; i < 4 ; i++) { DBbox subbox = _overlap.getcorner(i); clipedarea[i] = subbox.cliparea(shovl,true); if (-1 == clipedarea[i]) {//entirely inside the area if (!_quads[i]) _quads[i] = DEBUG_NEW quadTree(); _quads[i]->add(shape); return true; } } // if we got to this point - means that the shape does not fit // entirely inside neither of the four sub-areas. // It is a decision time then byte candidate = biggest(clipedarea); // now calculate the eventual new overlaping box DBbox newovl = _overlap.getcorner(candidate); newovl.overlap(shovl); // if the max area of the candidate does not blow more than 10% - // then seems to be OK to get it if (newovl.area() < 1.1 * (_overlap.area() / 4)) { if (!_quads[candidate]) _quads[candidate] = DEBUG_NEW quadTree(); _quads[candidate]->add(shape); return true; } return false; // shape can not be fit into any subtree }
/*! Build a new quadTree structure for the tdtdata in the inlist. The method is using the existing _overlap variable. For every layout shape fitinsubtree() method is called in a try to put the data in the child quadTree. At the end the method is called for every of the child structures. */ void laydata::quadTree::sort(dataList& inlist) { // if the input list is empty - nothing to do! if (0 == inlist.size()) return; dataList::iterator DI = inlist.begin(); // if the list contains only one component - link it and run away if (1 == inlist.size()) { DI->first->nextis(NULL); _first = DI->first; return; } byte i; // the overlapping box of the currnet shape // DBbox shovl(TP(0,0)); DBbox shovl = DEFAULT_OVL_BOX; // the maximum possible overlapping boxes of the 4 children DBbox maxsubbox[4] = {DEFAULT_OVL_BOX, DEFAULT_OVL_BOX, DEFAULT_OVL_BOX, DEFAULT_OVL_BOX}; for (i = 0; i < 4; i++) maxsubbox[i] = _overlap.getcorner(i); // the sub-lists data will be sorted in dataList sublist[4]; // which is the child where current shape fits int fitinsubbox; // initialize the iterator float sharea, totalarea = _overlap.area(); while (inlist.end() != DI) { // get the overlap of the current shape shovl = DI->first->overlap();shovl.normalize(); sharea = shovl.area(); // Check it fits in some of the children if (totalarea <= 4 * sharea || (-1 == (fitinsubbox = fitsubtree(shovl, maxsubbox)))) { // no fit. The shape is sorted in the current tree DI->first->nextis(_first); _first = DI->first; } else { // fits in sub-tree fitinsubbox sublist[fitinsubbox].push_back(*DI); // check this child already exists if (_quads[fitinsubbox]) // yes ? _quads[fitinsubbox]->_overlap.overlap(shovl); else { // create the child, initialize the overlapping box _quads[fitinsubbox] = DEBUG_NEW quadTree(); _quads[fitinsubbox]->_overlap = shovl; } } // in all cases get rid of the current shape pointer. It is already sorted DI = inlist.erase(DI); } // at this point inlist MUST be empty - split over max 4+this quadTrees // now go and sort the children - if any for(i = 0; i < 4; i++) if (_quads[i]) _quads[i]->sort(sublist[i]); }
int main(void) { sf::ContextSettings settings; settings.depthBits = 8; settings.stencilBits = 0; settings.antialiasingLevel = 0; settings.majorVersion = 3; settings.minorVersion = 3; sf::Window window(sf::VideoMode(1440, 900), "A Game", sf::Style::Default, settings); window.setFramerateLimit(60); glewInit(); glEnable(GL_DEPTH_TEST); EventQueue eventQueue; QuadTree quadTree(eventQueue, 2048); Renderer renderer({32, 32, 32, 32, 2048}, 512, 1440, 900); sf::Image img1; img1.loadFromFile("res/textures/test.png"); Texture tex1; tex1.loadFromImage(img1); sf::Image img2; img2.loadFromFile("res/textures/test2.png"); Texture tex2; tex2.loadFromImage(img2); std::vector<Platform> platforms_; std::vector<std::unique_ptr<GameObject>> gameObjects_; for (auto i=0u; i<10; ++i) { platforms_.emplace_back(quadTree, renderer, Vector2Glf(i*32.0f, 0.0f), Vector2Glf(32.0f, 32.0f), tex1, Vector2Glf(0.25f, 0.25f), 4); } sf::Image charImg; charImg.loadFromFile("res/textures/testChar.png"); Texture charTex; charTex.loadFromImage(charImg); gameObjects_.push_back(make_unique<Character>(quadTree, renderer, Vector2Glf(64.0f, 0.0f), Vector2Glf(64.0f, 64.0f), charTex, Vector2Glf(1.0f, 1.0f), 4)); /*for (auto j=0; j<4; ++j) { for (auto i=0; i<30; ++i) { Sprite& spr = renderer.getSpriteReference(); spr.setTexture(&tex2); spr.setPosition({ 128.0f*i, 128.0f*j - 256.0f }); spr.setDepth(0.5f); } }*/ /*for (auto i=0; i<10; ++i) { Sprite& spr = renderer.getSpriteReference(); spr.setTexture(&tex1); spr.setType(Sprite::TYPE_SOLID); spr.setScale({ 0.5f, 0.5f }); spr.setPosition({ 128.0f*i, 0.0f }); }*/ ParallaxBackground bg(renderer); bg.addLayer("res/textures/cityBackground4.png", 0, 0.2f, { 1000.0f, 0.0f }); bg.addLayer("res/textures/cityBackground3.png", 1, 0.3f, { 1000.0f, -600.0f }); bg.addLayer("res/textures/cityBackground2.png", 2, 0.6f, { 6000.0f, 40.0f }); bg.addLayer("res/textures/cityBackground1.png", 3, 0.75f, { 4500.0f, 50.0f }); Shader shader("shaders/VS_Sprite.glsl", "shaders/FS_Sprite.glsl"); ViewPort viewPort(1440.0f, 900.0f, Vector2Glf(0.0f, 0.0f)); viewPort.setPosition({ 512.0f, 0.0f }); float t = 0.0f; // The main loop - ends as soon as the window is closed while (window.isOpen()) { // Event processing sf::Event event; while (window.pollEvent(event)) { // Request for closing the window if (event.type == sf::Event::Closed) window.close(); } // Activate the window for OpenGL rendering glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); /*for (auto& o : gameObjects_) { o->update(); }*/ viewPort.setPosition({2160.0f+1440.0f*cos(t*PI*0.1 + PI), 0.0f}); bg.update(viewPort); renderer.render(viewPort, shader, t); window.display(); t += 1.0f/60.0f; } return 0; }
int main(int argc, char** argv) { if (argc<4) { fprintf(stderr,"%s node_in_file edge_in_file map_out_path",argv[0]); exit(-1); } const char* node_in_fname = argv[1]; const char* edge_in_fname = argv[2]; const char* map_out_path = argv[3]; MFRNodeArray nodes(node_in_fname); MFREdgeArray edges(edge_in_fname, nodes); fprintf(stderr,"Sort edges\n");fflush(stderr); qsort(edges.edges, edges.nredges, sizeof(MFREdgeInt), strength_compare); fprintf(stderr,"Max edge strength: %d\n",edges.edges[0].strength); if (edges.edges[0].strength < edges.edges[edges.nredges-1].strength) { fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@\nWrong sorting\n@@@@@@@@@@@@@@@@@@@@@@\n"); exit(-1); } fprintf(stderr,"Finished sorting edges\n");fflush(stderr); fprintf(stderr,"Count edges and store with nodes\n");fflush(stderr); { int i; for (i=0;i<edges.nredges;i++) { edges.edges[i].nodeA->totalnredges ++; edges.edges[i].nodeB->totalnredges ++; } } //ier@ fprintf(stderr,"Finished counting edges\n");fflush(stderr); fprintf(stderr,"Cleaning names (should perhaps be done earlier?)\n");fflush(stderr); nodes.CleanNames(); fprintf(stderr,"Finished cleaning names\n");fflush(stderr); // nodes.debug_show_if_sorted(12); MFRQuadTree quadTree(nodes, quadLevels); #define MAX_NODES_PER_QUAD 50 quadTree.BuildTree(MAX_NODES_PER_QUAD); quadTree.AssignQuadIds(); fprintf(stderr,"Writing out quadtree\n");fflush(stderr); nrquadnodeswritten = 0; int nredges = edges.nredges; int i; #define MAX_EDGES_PER_NODE 25 fprintf(stderr,"Collecting edges for quads (limited to max 25 per node)\n");fflush(stderr); CollectEdgesIntoQuads(nodes, edges, quadTree, MAX_EDGES_PER_NODE); fprintf(stderr, "Done assigning edges to quads (max 25 edges per node)\n");fflush(stderr); quadTree.DetermineStats(edges); fprintf(stderr,"Writing nodeid lookup table\n");fflush(stderr); WriteHashtable(map_out_path, nodes, edges, quadTree); WriteMap(map_out_path, nodes, edges, quadTree); { char fnamebuilder[1024]; if (quadLevels) { sprintf(fnamebuilder,"%squad_",map_out_path); WriteRootJSON(fnamebuilder, nodes, edges, quadTree, quadTree.root, ECompactModeCompact); sprintf(fnamebuilder,"%sequad_",map_out_path); WriteRootJSON(fnamebuilder, nodes, edges, quadTree, quadTree.root, ECompactModeExpanded); fprintf(stderr,"Collecting edges for quads (unlimited)\n");fflush(stderr); CollectEdgesIntoQuads(nodes, edges, quadTree, 0); fprintf(stderr, "Done assigning edges to quads (unlimited)\n");fflush(stderr); sprintf(fnamebuilder,"%sxquad_",map_out_path); WriteRootJSON(fnamebuilder, nodes, edges, quadTree, quadTree.root, ECompactModeFull); } else { sprintf(fnamebuilder,"%squad_",map_out_path); WriteRootJSON(fnamebuilder, nodes, edges, quadTree, quadTree.root, 0); } } fprintf(stderr,"Finisned\n");fflush(stderr); return 0; }