/*! Convert user (non-rectangular) mesh based data to internal structure. See also Qwt3D::TripleField and Qwt3D::CellField */ bool Curve::loadFromData(TripleField const& data, CellField const& poly, QString titlestr) { actualDataG_->clear(); actualData_p = actualDataC_; actualDataC_->datatype = Qwt3D::POLYGON; actualDataC_->nodes = data; actualDataC_->cells = poly; actualDataC_->normals = TripleField(actualDataC_->nodes.size()); if (!titlestr.isEmpty()) setTitle(titlestr); unsigned i; // normals for the moment Triple n, u, v; for (i = 0; i < poly.size(); ++i){ if (poly[i].size() < 3) n = Triple(0, 0, 0); else { for (unsigned j = 0; j < poly[i].size(); ++j){ unsigned jj = (j + 1) % poly[i].size(); unsigned pjj = (j) ? j - 1 : poly[i].size() - 1; u = actualDataC_->nodes[poly[i][jj]] - actualDataC_->nodes[poly[i][j]]; v = actualDataC_->nodes[poly[i][pjj]] - actualDataC_->nodes[poly[i][j]]; n = normalizedcross(u,v); actualDataC_->normals[poly[i][j]] += n; } } } for ( i = 0; i != actualDataC_->normals.size(); ++i) actualDataC_->normals[i].normalize(); ParallelEpiped hull(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX)); for (i = 0; i != data.size(); ++i){ Triple t = data[i]; if (t.x < hull.minVertex.x) hull.minVertex.x = t.x; if (t.y < hull.minVertex.y) hull.minVertex.y = t.y; if (t.z < hull.minVertex.z) hull.minVertex.z = t.z; if (t.x > hull.maxVertex.x) hull.maxVertex.x = t.x; if (t.y > hull.maxVertex.y) hull.maxVertex.y = t.y; if (t.z > hull.maxVertex.z) hull.maxVertex.z = t.z; } actualDataC_->setHull(hull); emit readInFinished(title()->string()); updateData(); return true; }
unsigned Qwt3D::tesselationSize(CellField const& t) { unsigned ret = 0; for (unsigned i=0; i!=t.size(); ++i) ret += t[i].size(); return ret; }
// ---------------------------------------------------------------------------- bool App::OnInit() { sf::RenderWindow m_Window(sf::VideoMode(800, 600), "Game of Life"); // list of objects to render every frame std::vector<Drawable*> renderList; // initialise background float zoomLimitMax = 2.0f; float zoomLimitMin = 0.125f; float zoomSmoothnessFactor = 4.0f; Background background; background.generate(); renderList.push_back( &background ); // initialise cell field bool mouseMoveKills = false; CellField cellField; renderList.push_back( &cellField ); // set up zooming parameters float currentZoom = 1.0f, targetZoom = 1.0f; sf::Vector2f viewPosition(0.0f,0.0f); sf::Vector2i pinchScrollPosition; bool isScrolling = false; // mouse states sf::Vector2i mousePosition; bool mouseButton1 = false; // cell timer, keeps track of when to update to next frame int cellTimer = 0; // speed of simulation int simulationSpeed = 5; // set to true when the game is paused bool isPaused = true; // set up loop timer LoopTimer loopTimer; loopTimer.setFPS( 60 ); // run the program as long as the window is open while( m_Window.isOpen() ) { // update game logic int maxUpdateLoops = 0; while( loopTimer.isTimeToUpdate() ) { // smooth zooming float deltaZoom = (currentZoom-targetZoom)/zoomSmoothnessFactor; currentZoom -= deltaZoom; // adjust view position so zoom occurs under mouse viewPosition.x += static_cast<float>(mousePosition.x)*deltaZoom/(currentZoom*currentZoom); viewPosition.y += static_cast<float>(mousePosition.y)*deltaZoom/(currentZoom*currentZoom); // calculate next frame if time has come if( !isPaused && cellTimer++ >= simulationSpeed ) { cellTimer = 0; cellField.calculateNextGeneration(); } // limit amount of update loops allowed if( ++maxUpdateLoops == 10 ) break; } // check all the window's events that were triggered since the last iteration of the loop sf::Event event; while( m_Window.pollEvent(event) ) { // "close requested" event: close the window if( event.type == sf::Event::Closed ) m_Window.close(); // handle zooming if( event.type == sf::Event::MouseWheelMoved ) { targetZoom += event.mouseWheel.delta/20.0f; if( targetZoom >= zoomLimitMax ) targetZoom = zoomLimitMax; if( targetZoom <= zoomLimitMin ) targetZoom = zoomLimitMin; } // mouse button pressed if( event.type == sf::Event::MouseButtonPressed ) { // press mouse if( event.mouseButton.button == sf::Mouse::Left ) mouseButton1 = true; // determine if further mouse movement should kill or revive cells int cellX = std::floor( (static_cast<float>(event.mouseButton.x)/currentZoom-viewPosition.x)/10.0f ); int cellY = std::floor( (static_cast<float>(event.mouseButton.y)/currentZoom-viewPosition.y)/10.0f ); if( cellField.isCellAlive(GOL::Vector2<int>(cellX,cellY)) ) { mouseMoveKills = true; if( mouseButton1 && isPaused ) cellField.removeCell(GOL::Vector2<int>(cellX,cellY)); }else { mouseMoveKills = false; if( mouseButton1 && isPaused ) cellField.addCell(GOL::Vector2<int>(cellX,cellY)); } // begin scrolling if( event.mouseButton.button == sf::Mouse::Right ) { isScrolling = true; pinchScrollPosition.x = event.mouseButton.x; pinchScrollPosition.y = event.mouseButton.y; } } // mouse button released if( event.type == sf::Event::MouseButtonReleased ) { // release mouse if( event.mouseButton.button == sf::Mouse::Left ) mouseButton1 = false; // end scrolling if( event.mouseButton.button == sf::Mouse::Right ) isScrolling = false; } // mouse movement if( event.type == sf::Event::MouseMoved ) { // set mouse position mousePosition.x = event.mouseMove.x; mousePosition.y = event.mouseMove.y; // handle scrolling if( isScrolling ) { viewPosition.x += static_cast<float>(event.mouseMove.x - pinchScrollPosition.x)/currentZoom; viewPosition.y += static_cast<float>(event.mouseMove.y - pinchScrollPosition.y)/currentZoom; pinchScrollPosition.x = event.mouseMove.x; pinchScrollPosition.y = event.mouseMove.y; } // handle killing/reviving cells in edit mode if( isPaused && mouseButton1 ) { int cellX = std::floor( (static_cast<float>(event.mouseMove.x)/currentZoom-viewPosition.x)/10.0f ); int cellY = std::floor( (static_cast<float>(event.mouseMove.y)/currentZoom-viewPosition.y)/10.0f ); if( mouseMoveKills ) cellField.removeCell(GOL::Vector2<int>(cellX,cellY)); else cellField.addCell(GOL::Vector2<int>(cellX,cellY)); } } // button presses if( event.type == sf::Event::KeyPressed ) { // pause/resume with space if( event.key.code == sf::Keyboard::Space ) { isPaused = !isPaused; } // increase simulation speed if( event.key.code == sf::Keyboard::Up ) if( simulationSpeed > 0 ) --simulationSpeed; // decrease simulation speed if( event.key.code == sf::Keyboard::Down ) if( simulationSpeed < 60 ) ++simulationSpeed; // reset field if( event.key.code == sf::Keyboard::Delete ) if( isPaused ) cellField.reset(); } } // clear m_Window.clear(); // draw everything to render window for( std::vector<Drawable*>::iterator it = renderList.begin(); it != renderList.end(); ++it ) (*it)->draw( &m_Window, sf::Vector2f(800,600), viewPosition, currentZoom ); // end the current frame m_Window.display(); } return true; }
/*! Convert user (non-rectangular) mesh based data to internal structure. See also Qwt3D::TripleField and Qwt3D::CellField */ bool SurfacePlot::loadFromData(TripleField const& data, CellField const& poly) { actualDataG_->clear(); actualData_p = actualDataC_; actualDataC_->nodes = data; actualDataC_->cells = poly; actualDataC_->normals = TripleField(actualDataC_->nodes.size()); unsigned i; // normals for the moment Triple n, u, v; for ( i = 0; i < poly.size(); ++i) { if (poly[i].size() < 3) n = Triple(0,0,0); else { for (unsigned j = 0; j < poly[i].size(); ++j) { unsigned jj = (j+1) % poly[i].size(); unsigned pjj = (j) ? j-1 : poly[i].size()-1; u = actualDataC_->nodes[poly[i][jj]]-actualDataC_->nodes[poly[i][j]]; v = actualDataC_->nodes[poly[i][pjj]]-actualDataC_->nodes[poly[i][j]]; n = normalizedcross(u,v); actualDataC_->normals[poly[i][j]] += n; } } } for ( i = 0; i != actualDataC_->normals.size(); ++i) { actualDataC_->normals[i].normalize(); } ParallelEpiped hull(Triple(DBL_MAX,DBL_MAX,DBL_MAX),Triple(-DBL_MAX,-DBL_MAX,-DBL_MAX)); for (i = 0; i!=data.size(); ++i) { if (data[i].x < hull.minVertex.x) hull.minVertex.x = data[i].x; if (data[i].y < hull.minVertex.y) hull.minVertex.y = data[i].y; if (data[i].z < hull.minVertex.z) hull.minVertex.z = data[i].z; if (data[i].x > hull.maxVertex.x) hull.maxVertex.x = data[i].x; if (data[i].y > hull.maxVertex.y) hull.maxVertex.y = data[i].y; if (data[i].z > hull.maxVertex.z) hull.maxVertex.z = data[i].z; } actualDataC_->setHull(hull); updateData(); updateNormals(); createCoordinateSystem(); return true; }