bool SlippyCoordinates::operator<(const SlippyCoordinates &other) const{ if(zoom()<other.zoom()) return true; if(zoom()>other.zoom()) return false; if(tilePos().x()<other.tilePos().x()) return true; if(tilePos().x()>other.tilePos().x()) return false; if(tilePos().y()<other.tilePos().y()) return true; if(tilePos().y()>other.tilePos().y()) return false; return false; // they are equal; }
void Tile::press(MapEditor& editor, QMouseEvent* pEvent) { if (pEvent->button() == Qt::RightButton || pEvent->button() == Qt::LeftButton) { // create brush auto brush = brushIndexFromMouseButton(pEvent->button()); auto pos = editor.mapToScene(pEvent->pos()).toPoint(); // if there is an old brush, release it _finishBrush(); try { m_pCurrentBrush = MAP::BRUSH::BrushFactory::createBrush(m_BrushInfos.at(static_cast<std::size_t>(brush)), m_DBMgr, editor.getMapData().getMapLayer(), editor.getLayerType(), editor.getLayerIndex() - 1); GEOMETRY::Point<uint32> tilePos(pos.x() / MAP::TILE_SIZE, pos.y() / MAP::TILE_SIZE); // if tileSet mapping, set brush size equal tileSet size if (m_BrushInfos.at(static_cast<std::size_t>(brush)).getType() == MAP::BRUSH::BrushInfo::Type::TILE_SET) { if (auto pTileSet = m_DBMgr.getTileSetDatabase().getPrototype(m_BrushInfos.at(static_cast<std::size_t>(brush)).getID())) m_pCurrentBrush->setBrushSize(pTileSet->getSize()); } m_pCurrentBrush->start(tilePos); editor.scene()->update(); m_pCurrentEditor = &editor; } catch (const MAP::EXCEPTION::LayerOutOfRangeException&) {} } }
bool MapMarker :: draw(const NE::Renderer& r, const Camera& c, const unsigned int time) { UVec2 cameraPosition = c.getPosition(); IVec2 tilePos(0,0); bool bResult = true; // The camera is an offset of the Map drawing // For each lines for ( unsigned int y = cameraPosition.y ; y < MAP_MIN_HEIGHT+cameraPosition.y ; y++ ) { tilePos.x = 0;//mapOffset.width; // For each columns for ( unsigned int x = cameraPosition.x ; x < MAP_MIN_WIDTH+cameraPosition.x ; x++ ) { if ( marks[y][x] != -1 ) // If we have a mark { bResult &= pMarkerSprite->draw(r,tilePos,time); } // Move on the right tilePos.x += TILE_DEFAULT_WIDTH; } // To put 0 here, can be a bit dangerous tilePos.y += TILE_DEFAULT_HEIGHT; } return bResult; }
void CPrivilagedInfoCallback::getTilesInRange( std::unordered_set<int3, ShashInt3> &tiles, int3 pos, int radious, boost::optional<PlayerColor> player/*=uninit*/, int mode/*=0*/, bool patrolDistance/*=false*/) const { if(!!player && *player >= PlayerColor::PLAYER_LIMIT) { logGlobal->errorStream() << "Illegal call to getTilesInRange!"; return; } if (radious == -1) //reveal entire map getAllTiles (tiles, player, -1, 0); else { const TeamState * team = !player ? nullptr : gs->getPlayerTeam(*player); for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++) { for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++) { int3 tilePos(xd,yd,pos.z); double distance; if(patrolDistance) distance = pos.mandist2d(tilePos); else distance = pos.dist2d(tilePos) - 0.5; if(distance <= radious) { if(!player || (mode == 1 && team->fogOfWarMap[xd][yd][pos.z]==0) || (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1) ) tiles.insert(int3(xd,yd,pos.z)); } } } } }
float2 Hero::adjustRopeDirection(float2 direction) { float bestScore = 0; float2 bestDirection = direction; for (int y = 0; y < mRoom->getHeightInTiles(); y++) { for (int x = 0; x < mRoom->getWidthInTiles(); x++) { if (mRoom->isHookable(x, y)) { float pixelX = x * mRoom->getTileWidth() + mRoom->getTileWidth() / 2; float pixelY = y * mRoom->getTileHeight() + mRoom->getTileHeight() / 2; float2 tilePos(pixelX, pixelY); float score = getAutoAimScore(direction, tilePos); if (score > bestScore) { float2 direction = tilePos - mPosition; int rcX, rcY; bool rcHit = mRoom->rayCast(mPosition, direction, false, rcX, rcY); if (rcHit && rcX == x && rcY == y) { bestScore = score; bestDirection = direction; } } } } } std::vector<Entity *> &damagableEntities = mRoom->getDamagableEntities(); std::vector<Entity *> &hookableEntities = mRoom->getHookableEntities(); std::vector<Entity *> entities; entities.insert( entities.end(), damagableEntities.begin(), damagableEntities.end() ); entities.insert( entities.end(), hookableEntities.begin(), hookableEntities.end() ); for (int i = 0; i < (int)entities.size(); i++) { Entity *e = entities[i]; float2 entityPos = e->getPosition(); float score = getAutoAimScore(direction, entityPos); if (score > bestScore) { float2 direction = entityPos - mPosition; int rcX, rcY; bool rcHit = mRoom->rayCast(mPosition, direction, false, rcX, rcY); float2 rcTilePos(rcX * mRoom->getTileWidth() + mRoom->getTileWidth() / 2, rcY * mRoom->getTileHeight() + mRoom->getTileHeight() / 2); if (!rcHit || lengthCompare(direction, rcTilePos) < 0) { bestScore = score; bestDirection = direction; } } } return normalize(bestDirection); }
void RandomTower::Draw(const math::bbox2f &screen) { math::vec2i start = tilePos(screen.min); math::vec2i end = tilePos(screen.max) + math::vec2i(1,1); for (int j = start.y; j < end.y; ++j) { drawDeletedTiles(j); for (int i = start.x; i < end.x; ++i) { math::bbox2f quad( math::vec2f(i,j)*m_unitsPerTile, math::vec2f(i+1,j+1)*m_unitsPerTile); if (isColl(i,j)) { glColor(Guy::rgb(0.400f, 0.275f, 0.195f)); Guy::draw(quad); } } } }
void MapEditor::createGrid(){ std::string currentLevelName = Toolbox::getCurrentLevelName(); if (currentLevelName == "Throat") { mMapDimensionsTiles = sf::Vector2f(50, 500); } else if (currentLevelName == "Stomach") { mMapDimensionsTiles = sf::Vector2f(500, 50); } else if (currentLevelName == "Hub") { mMapDimensionsTiles = sf::Vector2f(100, 100); } else if (currentLevelName == "Intestine") { mMapDimensionsTiles = sf::Vector2f(250, 350); } else if (currentLevelName == "Mouth") { mMapDimensionsTiles = sf::Vector2f(500, 50); } mGrid.clear(); sf::Vector2f lastTilePos(-mTileDimensions.x, -mTileDimensions.y); //std::vector<sf::Sprite> tiles; for (size_t i = 0; i < mMapDimensionsTiles.x; i++){ sf::Vector2f tilePos(0, -1000); tilePos.x = lastTilePos.x; tilePos.x += mTileDimensions.x; sf::Sprite xTile; xTile.setTexture(mTileTexture); xTile.setPosition(tilePos); mGrid.push_back(xTile); //std::cout << "X: " << xTile.getPosition().x << std::endl << "Y: " << xTile.getPosition().y << std::endl << std::endl; for (size_t j = 0; j < mMapDimensionsTiles.y - 1; j++){ tilePos.y += mTileDimensions.y; sf::Sprite yTile; yTile.setTexture(mTileTexture); yTile.setPosition(tilePos); mGrid.push_back(yTile); lastTilePos = tilePos; //std::cout << "X: " << yTile.getPosition().x << std::endl << "Y: " << yTile.getPosition().y << std::endl << std::endl; } lastTilePos.y = 0; lastTilePos.x = tilePos.x; } std::cout << "Tiles created: " << mGrid.size() << std::endl; }
void Tile::move(MapEditor& editor, QMouseEvent* pEvent) { if (m_pCurrentEditor && &editor == m_pCurrentEditor) { try { auto pos = editor.mapToScene(pEvent->pos()).toPoint(); GEOMETRY::Point<uint32> tilePos(pos.x() / MAP::TILE_SIZE, pos.y() / MAP::TILE_SIZE); m_pCurrentBrush->start(tilePos); m_pCurrentEditor->scene()->update(); } catch (const MAP::EXCEPTION::LayerOutOfRangeException&) {} } else _finishBrush(); }
void TurnOffTiles::update(float time) { unsigned int l = (unsigned int)(time * (float)_tilesCount); unsigned int t = 0; for (unsigned int i = 0; i < _tilesCount; i++ ) { t = _tilesOrder[i]; Vec2 tilePos( (unsigned int)(t / _gridSize.height), t % (unsigned int)_gridSize.height ); if ( i < l ) { turnOffTile(tilePos); } else { turnOnTile(tilePos); } } }
void ScreenShot::tileGui( const Point2I &screenSize ) { AssertFatal( mPending, "ScreenShot::tileGui() - This should only be called during screenshots!" ); // We do not need to make changes on a single tile. if ( mTiles == 1 ) return; GFX->setWorldMatrix( MatrixF::Identity ); S32 currTileX = mCurrTile.x; S32 currTileY = (S32)mTiles - mCurrTile.y - 1; //Vertically flipped tile index MatrixF tileMat( true ); Point3F tilePos(0,0,0); tilePos.x = currTileX * (-screenSize.x) + mPixelOverlap.x * screenSize.x * (currTileX * 2 + 1); tilePos.y = currTileY * (-screenSize.y) + mPixelOverlap.y * screenSize.y * (currTileY * 2 + 1); tileMat.setPosition( tilePos + Point3F(0.5f, 0.5f, 0) ); tileMat.scale( Point3F( (F32)mTiles * (1-mPixelOverlap.x*2), (F32)mTiles * (1-mPixelOverlap.y*2), 0 ) ); GFX->setViewMatrix( tileMat ); }
void RunnerTilemap::draw(const math::bbox2d &screen) { math::vec2i start = tilePos(screen.min); math::vec2i end = tilePos(screen.max) + math::vec2i(1,1); if ((int)m_chunks.size() <= end.x) generateUntil(end.x); glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glDisable(GL_BLEND); unsigned short c = 0; glColor(m_color); if (start.y < 0) { math::bbox2d quad( math::vec2d((double)start.x,(double) start.y)*m_unitsPerTile, math::vec2d((double)1+end.x,(double) 0)*m_unitsPerTile); fillVertexArray(0, quad); drawVertexArray(1); start.y = 0; } if (start.x < 0) start.x = 0; for (int i = start.x; i < end.x; ++i) { chunk& cur = m_chunks[i]; bool lastColl = false; int lastColly = start.y; for (int j = start.y; j < end.y; ++j) { bool currColl = (j < 0) || (cur.height > j) || ((int)cur.ceil > 4 && (int)(cur.ceil + cur.height) < j); if (!lastColl && currColl) lastColly = j; else if (lastColl && !currColl) { math::bbox2d quad( math::vec2d((double) i+0,(double) lastColly)*m_unitsPerTile, math::vec2d((double) i+1,(double) j)*m_unitsPerTile); fillVertexArray(c, quad); if (++c == VERTEX_ARRAY_SIZE) { drawVertexArray(c); c = 0; } } lastColl = currColl; } if (lastColl) { math::bbox2d quad( math::vec2d((double) i+0,(double) lastColly)*m_unitsPerTile, math::vec2d((double) i+1,(double) end.y)*m_unitsPerTile); fillVertexArray(c, quad); if (++c == VERTEX_ARRAY_SIZE) { drawVertexArray(c); c = 0; } } } if (c) drawVertexArray(c); }
void Map::draw(const Rect& rect) { if(!m_framebuffer) { m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS)); program = PainterShaderProgramPtr(new PainterShaderProgram); program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); program->addShaderFromSourceFile(Shader::Fragment, "/shadertest.frag"); assert(program->link()); } g_painter.setColor(Fw::white); m_framebuffer->bind(); // draw offsets LocalPlayerPtr localPlayer = g_game.getLocalPlayer(); if(localPlayer) m_drawOffset = localPlayer->getWalkOffset(); //TODO: cache first/last visible floor // draw from bottom floors to top floors int firstFloor = getFirstVisibleFloor(); const int lastFloor = MAX_Z-1; for(int iz = lastFloor; iz >= firstFloor; --iz) { // draw tiles like linus pauling's rule order const int numDiagonals = m_size.width() + m_size.height() - 1; for(int diagonal = 0; diagonal < numDiagonals; ++diagonal) { // loop through / diagonal tiles for(int ix = std::min(diagonal, m_size.width() - 1), iy = std::max(diagonal - m_size.width(), 0); ix >= 0 && iy < m_size.height(); --ix, ++iy) { // position on current floor Position tilePos(m_centralPosition.x + (ix - m_centralOffset.x), m_centralPosition.y + (iy - m_centralOffset.y), m_centralPosition.z); // adjust tilePos to the wanted floor tilePos.perspectiveUp(m_centralPosition.z - iz); //TODO: cache visible tiles, m_tiles[] has a high cost (50% fps decrease) if(const TilePtr& tile = m_tiles[tilePos]) { // skip tiles that are behind another tile //if(isCompletlyCovered(tilePos, firstFloor)) // continue; tile->draw(positionTo2D(tilePos) - m_drawOffset); } } } // after drawing all tiles, draw shots for(const MissilePtr& shot : m_missilesAtFloor[iz]) { Position missilePos = shot->getPosition(); shot->draw(positionTo2D(missilePos) - m_drawOffset); } } m_framebuffer->release(); g_painter.setCustomProgram(program); g_painter.setColor(Fw::white); m_framebuffer->draw(rect); g_painter.releaseCustomProgram(); // calculate stretch factor float horizontalStretchFactor = rect.width() / (float)(m_visibleSize.width() * NUM_TILE_PIXELS); float verticalStretchFactor = rect.height() / (float)(m_visibleSize.height() * NUM_TILE_PIXELS); // draw player names and health bars //TODO: this must be cached with creature walks for(int x = 0; x < m_visibleSize.width(); ++x) { for(int y = 0; y < m_visibleSize.height(); ++y) { Position tilePos = Position(m_centralPosition.x + (x - m_centralOffset.x + 1), m_centralPosition.y + (y - m_centralOffset.y + 1), m_centralPosition.z); if(const TilePtr& tile = m_tiles[tilePos]) { auto creatures = tile->getCreatures(); if(creatures.size() == 0) continue; for(const CreaturePtr& creature : creatures) { Point p((m_centralOffset.x - 1 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawElevation(), (m_centralOffset.y - 1 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawElevation()); if(creature != localPlayer) { p += creature->getWalkOffset() - m_drawOffset; } creature->drawInformation(rect.x() + p.x*horizontalStretchFactor, rect.y() + p.y*verticalStretchFactor, isCovered(tilePos, firstFloor), rect); } } } } }
void CharacterIn2D::UpdateTopDown(CMap *map, double dt) { //Calculate the friction force float frictionForce = this->m_mass * GRAVITY * FRICTIONCOEFFICENT; Vector2 frictionDirection; if(m_velocity.Length() != 0) { frictionDirection = -m_velocity.Normalized(); } else { frictionDirection.Set(0,0); } Vector2 frictionInOppositeDirection = frictionDirection * frictionForce; m_velocity = m_velocity + (frictionInOppositeDirection * dt); // New position next frame Vector2 tilePos( (map->GetmapOffset().x + (this->GetPosition().x - (this->m_velocity.x * dt))) / map->GetTileSize() , map->GetNumOfTiles_Height() - (int) (ceil((float)(this->GetPosition().y + map->GetTileSize()) / map->GetTileSize())) ); if(m_facingNormal.x > 0) { if(map->theScreenMap[tilePos.y][tilePos.x+1] > 0) { this->m_position.x = this->m_position.x + (m_velocity.x * dt); } else { m_velocity.x = 0; } } else if(m_facingNormal.x < 0) { if(map->theScreenMap[tilePos.y][tilePos.x] > 0) { this->m_position.x = this->m_position.x + (m_velocity.x * dt); } else { m_velocity.x = 0; } } if(m_facingNormal.y > 0) { if(map->theScreenMap[tilePos.y][tilePos.x] > 0 && map->theScreenMap[tilePos.y][tilePos.x+1] > 0) { this->m_position.y = this->m_position.y + (m_velocity.y * dt); } else { m_velocity.y = 0; } } else if(m_facingNormal.y < 0) { if(map->theScreenMap[tilePos.y+1][tilePos.x] > 0 && map->theScreenMap[tilePos.y+1][tilePos.x+1] > 0) { this->m_position.y = this->m_position.y + (m_velocity.y * dt); } else { m_velocity.y = 0; } } if(m_velocity.Length() < 1.f) { m_velocity.Set(0,0); } }
///============================================================================= bool mergeVertices(sm2obj::entityInfoStruct* Input, const std::string& InputOutputTemp, ffw::file* Output, bool SplitTextures, bool ExportUvMaps){ Output->writeLine("o " + Input->name); for(auto& chunk : Input->chunks){ ffw::file vertices; // Open chunk temp file which contains vertices if(!vertices.open(InputOutputTemp + "\\chunk-temp-" + ffw::valToString(chunk.fileIndex) + ".vertices", std::ios::in)){ ffw::logError() << "Error failed to open vertex temp data! Index: " << chunk.fileIndex; return false; } // Read whole file and put contents in output OBJ std::string temp; while(!vertices.eof()){ vertices.readLine(&temp); if(temp.size() == 0)continue; Output->writeLine(temp); } } // Export UVs if(ExportUvMaps && SplitTextures){ for(int i = 0; i < 4; i++){ Output->writeLine("vt " + ffw::valToString(sm2obj::globalTextureUvs[i].x, 6) + " " + ffw::valToString(sm2obj::globalTextureUvs[i].y, 6)); } } else if(ExportUvMaps){ for(const auto& tile : Input->extractedTiles){ int atlasId = tile / 256; int posY = tile / 16; int posX = tile - posY*16; posY -= atlasId*16; ffw::vec2f tilePos(posX / 16.0f, posY / 16.0f); tilePos.y = 1.0f - tilePos.y - 0.0625f; for(int i = 0; i < 4; i++){ ffw::vec2f uvs = sm2obj::globalTextureUvs[i]; uvs.y = 1.0f - uvs.y; ffw::vec2f texPos = uvs * ffw::vec2f(0.052734375f, 0.052734375f) + tilePos + 0.0048828125f; Output->writeLine("vt " + ffw::valToString(texPos.x, 10) + " " + ffw::valToString(texPos.y, 10)); } } } // Shading off Output->writeLine("s off"); // Do the same for indices for(auto& chunk : Input->chunks){ ffw::file indices; // Open chunk temp file which contains indices if(!indices.open(InputOutputTemp + "\\chunk-temp-" + ffw::valToString(chunk.fileIndex) + ".indices", std::ios::in)){ ffw::logError() << "Error failed to open indice temp data! Index: " << chunk.fileIndex; return false; } // Read whole file and put contents in output OBJ std::string temp; while(!indices.eof()){ indices.readLine(&temp); if(temp.size() == 0)continue; Output->writeLine(temp); } } return true; }
//Rasterize 4 pixels at once void DepthBuffer::rasterizeTile2x2(int32 x,int32 y,uint32 pass) { auto tileIndex = x + y*tileCount_.x; auto count = tileTriangleCount_[tileIndex]; tileTriangleCount_[tileIndex] = 0; auto faces = triangleBins_ + x*kMaxTrianglesPerTile + y*tileCount_.x*kMaxTrianglesPerTile; vec2i tilePos(x*tileSize_.x,y*tileSize_.y); vec2i tileEnd(tilePos + tileSize_); #ifdef ARPHEG_ARCH_X86 enum { kNumLanes = 4 }; //Flush denormals to zero _mm_setcsr( _mm_getcsr() | 0x8040 ); VecS32 colOffset(0, 1, 0, 1); VecS32 rowOffset(0, 0, 1, 1); //Process the 4 binned triangles at a time VecS32 vertexX[3]; VecS32 vertexY[3]; VecF32 vertexZ[4]; VecS32 tileMinXSimd(tilePos.x); VecS32 tileMaxXSimd(tilePos.x+tileSize_.x-2); VecS32 tileMinYSimd(tilePos.y); VecS32 tileMaxYSimd(tilePos.y+tileSize_.y-2); for(uint32 i = 0;i<count;i += kNumLanes){ uint32 numSimdTris = std::min(uint32(kNumLanes),count-i); auto f = faces+i; for(uint32 ii = 0;ii< numSimdTris;++ii){ vertexX[0].lane[ii] = f[ii].v[0].x; vertexY[0].lane[ii] = f[ii].v[0].y; vertexX[1].lane[ii] = f[ii].v[1].x; vertexY[1].lane[ii] = f[ii].v[1].y; vertexX[2].lane[ii] = f[ii].v[2].x; vertexY[2].lane[ii] = f[ii].v[2].y; vertexZ[ii] = VecF32(f[ii].z[0],f[ii].z[1],f[ii].z[2],0.0f); } // Fab(x, y) = Ax + By + C = 0 // Fab(x, y) = (ya - yb)x + (xb - xa)y + (xa * yb - xb * ya) = 0 // Compute A = (ya - yb) for the 3 line segments that make up each triangle VecS32 A0 = vertexY[1] - vertexY[2]; VecS32 A1 = vertexY[2] - vertexY[0]; VecS32 A2 = vertexY[0] - vertexY[1]; // Compute B = (xb - xa) for the 3 line segments that make up each triangle VecS32 B0 = vertexX[2] - vertexX[1]; VecS32 B1 = vertexX[0] - vertexX[2]; VecS32 B2 = vertexX[1] - vertexX[0]; // Compute C = (xa * yb - xb * ya) for the 3 line segments that make up each triangle VecS32 C0 = vertexX[1] * vertexY[2] - vertexX[2] * vertexY[1]; VecS32 C1 = vertexX[2] * vertexY[0] - vertexX[0] * vertexY[2]; VecS32 C2 = vertexX[0] * vertexY[1] - vertexX[1] * vertexY[0]; // Use bounding box traversal strategy to determine which pixels to rasterize VecS32 minX = vmax(vmin(vmin(vertexX[0], vertexX[1]), vertexX[2]), tileMinXSimd) & VecS32(~1); VecS32 maxX = vmin(vmax(vmax(vertexX[0], vertexX[1]), vertexX[2]), tileMaxXSimd); VecS32 minY = vmax(vmin(vmin(vertexY[0], vertexY[1]), vertexY[2]), tileMinYSimd) & VecS32(~1); VecS32 maxY = vmin(vmax(vmax(vertexY[0], vertexY[1]), vertexY[2]), tileMaxYSimd); //Rasterize each triangle individually for(uint32 lane = 0;lane < numSimdTris;++lane){ //Rasterize in 2x2 quads. VecF32 zz[3]; zz[0] = VecF32(vertexZ[lane].lane[0]); zz[1] = VecF32(vertexZ[lane].lane[1]); zz[2] = VecF32(vertexZ[lane].lane[2]); VecS32 a0(A0.lane[lane]); VecS32 a1(A1.lane[lane]); VecS32 a2(A2.lane[lane]); VecS32 b0(B0.lane[lane]); VecS32 b1(B1.lane[lane]); VecS32 b2(B2.lane[lane]); int32 minx = minX.lane[lane]; int32 maxx = maxX.lane[lane]; int32 miny = minY.lane[lane]; int32 maxy = maxY.lane[lane]; VecS32 col = VecS32(minx) + colOffset; VecS32 row = VecS32(miny) + rowOffset; auto rowIdx = miny*size_.x + 2 * minx; VecS32 w0_row = a0 * col + b0 * row + VecS32(C0.lane[lane]); VecS32 w1_row = a1 * col + b1 * row + VecS32(C1.lane[lane]); VecS32 w2_row = a2 * col + b2 * row + VecS32(C2.lane[lane]); //Multiply each weight by two(rasterize 2x2 quad at once). a0 = shiftl<1>(a0); a1 = shiftl<1>(a1); a2 = shiftl<1>(a2); b0 = shiftl<1>(b0); b1 = shiftl<1>(b1); b2 = shiftl<1>(b2); VecF32 zInc = itof(a1)*zz[1] + itof(a2)*zz[2]; for(int32 y = miny;y<=maxy;y+=2,rowIdx += 2 * size_.x){ auto w0 = w0_row; auto w1 = w1_row; auto w2 = w2_row; VecF32 depth = zz[0] + itof(w1)*zz[1] + itof(w2)*zz[2]; auto idx = rowIdx; for(int32 x = minx;x<=maxx;x+=2,idx+=4){ auto mask = w0|w1|w2; VecF32 previousDepth = VecF32::load(data_+idx); VecF32 mergedDepth = vmin(depth,previousDepth); previousDepth = select(mergedDepth,previousDepth,mask); previousDepth.store(data_+idx); w0+=a0; w1+=a1; w2+=a2; depth+=zInc; } w0_row += b0; w1_row += b1; w2_row += b2; } } } #endif }
void DepthBuffer::rasterizeTile(int32 x,int32 y,uint32 pass) { if(pass == 0){ //init tile(clear depth). //auto tilePixels = data_ + x*tileSize_.x*tileSize_.y + (y*tileSize_.x*tileSize_.y)*tileCount_.x; //clearDepth(tilePixels,tileSize_.x*tileSize_.y,1.0f); } if(mode_ == kModeDepthPackedQuads){ rasterizeTile2x2(x,y,pass); return; } auto tileIndex = x + y*tileCount_.x; auto count = tileTriangleCount_[tileIndex]; tileTriangleCount_[tileIndex] = 0; auto faces = triangleBins_ + x*kMaxTrianglesPerTile + y*tileCount_.x*kMaxTrianglesPerTile; vec2i tilePos(x*tileSize_.x,y*tileSize_.y); vec2i tileEnd(tilePos + tileSize_); #ifdef ARPHEG_ARCH_X86 enum { kNumLanes = 4 }; //Flush denormals to zero //_mm_setcsr( _mm_getcsr() | 0x8040 ); VecS32 colOffset(0, 1, 0, 1); VecS32 rowOffset(0, 0, 1, 1); //Process the 4 binned triangles at a time VecS32 vertexX[3]; VecS32 vertexY[3]; VecF32 vertexZ[4]; VecS32 tileMinXSimd(tilePos.x); VecS32 tileMaxXSimd(tilePos.x+tileSize_.x-1); VecS32 tileMinYSimd(tilePos.y); VecS32 tileMaxYSimd(tilePos.y+tileSize_.y-1); for(uint32 i = 0;i<count;i += kNumLanes){ uint32 numSimdTris = std::min(uint32(kNumLanes),count-i); auto f = faces+i; for(uint32 ii = 0;ii< numSimdTris;++ii){ vertexX[0].lane[ii] = f[ii].v[0].x; vertexY[0].lane[ii] = f[ii].v[0].y; vertexX[1].lane[ii] = f[ii].v[1].x; vertexY[1].lane[ii] = f[ii].v[1].y; vertexX[2].lane[ii] = f[ii].v[2].x; vertexY[2].lane[ii] = f[ii].v[2].y; vertexZ[ii] = VecF32(f[ii].z[0],f[ii].z[1],f[ii].z[2],0.0f); } // Fab(x, y) = Ax + By + C = 0 // Fab(x, y) = (ya - yb)x + (xb - xa)y + (xa * yb - xb * ya) = 0 // Compute A = (ya - yb) for the 3 line segments that make up each triangle VecS32 A0 = vertexY[1] - vertexY[2]; VecS32 A1 = vertexY[2] - vertexY[0]; VecS32 A2 = vertexY[0] - vertexY[1]; // Compute B = (xb - xa) for the 3 line segments that make up each triangle VecS32 B0 = vertexX[2] - vertexX[1]; VecS32 B1 = vertexX[0] - vertexX[2]; VecS32 B2 = vertexX[1] - vertexX[0]; // Compute C = (xa * yb - xb * ya) for the 3 line segments that make up each triangle VecS32 C0 = vertexX[1] * vertexY[2] - vertexX[2] * vertexY[1]; VecS32 C1 = vertexX[2] * vertexY[0] - vertexX[0] * vertexY[2]; VecS32 C2 = vertexX[0] * vertexY[1] - vertexX[1] * vertexY[0]; // Use bounding box traversal strategy to determine which pixels to rasterize VecS32 minX = vmax(vmin(vmin(vertexX[0], vertexX[1]), vertexX[2]), tileMinXSimd); VecS32 maxX = vmin(vmax(vmax(vertexX[0], vertexX[1]), vertexX[2]), tileMaxXSimd); VecS32 minY = vmax(vmin(vmin(vertexY[0], vertexY[1]), vertexY[2]), tileMinYSimd); VecS32 maxY = vmin(vmax(vmax(vertexY[0], vertexY[1]), vertexY[2]), tileMaxYSimd); //Rasterize each triangle individually for(uint32 lane = 0;lane < numSimdTris;++lane){ float zz[3] = { vertexZ[lane].lane[0],vertexZ[lane].lane[1],vertexZ[lane].lane[2] }; int32 a0 = A0.lane[lane]; int32 a1 = A1.lane[lane]; int32 a2 = A2.lane[lane]; int32 b0 = B0.lane[lane]; int32 b1 = B1.lane[lane]; int32 b2 = B2.lane[lane]; int32 minx = minX.lane[lane]; int32 maxx = maxX.lane[lane]; int32 miny = minY.lane[lane]; int32 maxy = maxY.lane[lane]; auto w0_row = a0 * minx + b0 * miny + C0.lane[lane]; auto w1_row = a1 * minx + b1 * miny + C1.lane[lane]; auto w2_row = a2 * minx + b2 * miny + C2.lane[lane]; float* tilePixels = data_ + tilePos.x*tileSize_.y + (tilePos.y*tileSize_.x)*tileCount_.x; int32 idx2 = minx-tilePos.x + (miny - tilePos.y)*tileSize_.x; int32 spanx = maxx-minx; for(int32 endIdx2 = idx2+(tileSize_.x)*(maxy-miny);idx2<=endIdx2;idx2+=tileSize_.x){ auto w0 = w0_row; auto w1 = w1_row; auto w2 = w2_row; auto idx = idx2; for(int32 endIdx = idx+spanx;idx<=endIdx;++idx){ auto mask = w0|w1|w2; if(mask >= 0){ float betaf = float(w1); float gamaf = float(w2); float depth = zz[0] + betaf*zz[1] + gamaf*zz[2]; auto d = tilePixels[idx]; d = depth<d?depth:d; tilePixels[idx] = d; } w0+=a0; w1+=a1; w2+=a2; } w0_row += b0; w1_row += b1; w2_row += b2; } } } #else for(uint32 i = 0;i<count;i ++){ drawTriangle(faces[i],tilePos); } #endif }