void SprayBrush::paintMetaballs(KisPaintDeviceSP dev, const KisPaintInformation &info, const KoColor &painterColor) { // TODO: make adjustable? qreal MIN_TRESHOLD = m_mintresh; qreal MAX_TRESHOLD = m_maxtresh; // dbgPlugins << "MAX " << MAX_TRESHOLD; // dbgPlugins << "MIN " << MIN_TRESHOLD; KoColor color = painterColor; qreal posX = info.pos().x(); qreal posY = info.pos().y(); //int points = m_coverage * (m_radius * m_radius * M_PI); qreal ballRadius = m_width * 0.5; // generate metaballs QList<Metaball> list; for (int i = 0; i < m_particlesCount ; i++){ qreal x = (2 * drand48() * m_radius) - m_radius; qreal y = (2 * drand48() * m_radius) - m_radius; list.append( Metaball( x, y , drand48() * ballRadius) ); } // paint it KisRandomAccessor accessor = dev->createRandomAccessor(0, 0); qreal sum = 0.0; m_computeArea.translate( -qRound(posX), -qRound(posY) ); for (int y = m_computeArea.y(); y <= m_computeArea.height(); y++){ for (int x = m_computeArea.x() ; x <= m_computeArea.width(); x++){ sum = 0.0; for (int i = 0; i < m_particlesCount; i++){ sum += list[i].equation(x, y ); } if (sum >= MIN_TRESHOLD && sum <= MAX_TRESHOLD){ if (sum < 0.0) sum = 0.0; if (sum > 1.0) sum = 1.0; color.setOpacity(OPACITY_OPAQUE * sum); accessor.moveTo( x + posX ,y + posY ); memcpy(accessor.rawData(), color.data(), dev->colorSpace()->pixelSize() ); } } } m_computeArea.translate( qRound(posX), qRound(posY) ); #if 0 KisPainter dabPainter(dev); dabPainter.setFillColor(color); dabPainter.setPaintColor(color); dabPainter.setFillStyle(KisPainter::FillStyleForegroundColor); for (int i = 0; i < m_particlesCount; i++){ qreal x = list[i].x() + posX; qreal y = list[i].y() + posY; dabPainter.paintEllipse(x, y, list[i].radius() * 2,list[i].radius() * 2); } #endif }
int GenLagoonZone::makeItRain(int numLakes, int tam){ int screenN; //actual screen number int screenX, screenY; //coordenadas X Y de la screen Actual int tileX, tileY; //coordenadas X Y sobre el mapa mundi del tile izq-arriba de la matriz de la pantalla int numSolids = 0; int tilesPerRow = overworld->getTileWorldSizeW(); //int desp = screenList->size() / numLakes; int actualScreen = rand()%screenList->size(); vector<bool> visited(screenList->size()); bool foundNew = false; for(int i=0; i < numLakes; i++) { foundNew = false; screenN = screenList->at(actualScreen)->getScreenNumber(); //cogemos una screen //coordenadas de la screenN dentro del mundo. screenX = screenN % overworld->getWorldSizeW(); screenY = screenN / overworld->getWorldSizeW(); // coordenada X e Y del tile inicial de pantalla tileX = screenX * SCREEN_WIDTH; tileY = screenY * SCREEN_HEIGHT; Metaball meta = Metaball(rand()%SCREEN_WIDTH + tileX, rand()%SCREEN_HEIGHT + tileY, (float)(rand()%tam)+10, SHAPE_BALL);//rand()%3); meta.xm = rand()%50 * 0.01f; meta.ym = rand()%50 * 0.01f; lakes.push_back(meta); //actualScreen = (actualScreen + desp) % screenList->size(); while(!foundNew) { actualScreen = rand()%screenList->size(); if (!visited[actualScreen]) { visited[actualScreen] = true; foundNew = true; } } } const float MAX_THRESHOLD = 1.1f; const float MIN_THRESHOLD = 0.9f; // Value to act as a summation of all Metaballs' fields applied to this particular tile float sum; // Pasamos por todas las screens de la zona for (int j=0; j<(int)screenList->size(); j++) { screenN = screenList->at(j)->getScreenNumber(); screenX = screenN % overworld->getWorldSizeW(); screenY = screenN / overworld->getWorldSizeW(); // coordenada X e Y del tile inicial de pantalla tileX = screenX * SCREEN_WIDTH; tileY = screenY * SCREEN_HEIGHT; // Iterate over every tile on the screen for(int x = 0; x < SCREEN_WIDTH; x++){ for(int y = 0; y < SCREEN_HEIGHT; y++){ // Reset the summation sum = 0; // Iterate through every Metaball in the zone for(int i = 0; i < (int)lakes.size(); i++){ sum += lakes[i].flow(tileX+x,tileY+y); } // Decide whether to draw a water tile if(sum >= MIN_THRESHOLD /*&& sum <= MAX_THRESHOLD*/) { screenList->at(j)->setSolid(x,y,2); // put water numSolids++; } } } } return numSolids; }