예제 #1
0
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;
}
예제 #2
0
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&) {}
    }
}
예제 #3
0
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;
}
예제 #4
0
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));
				}
			}
		}
	}
}
예제 #5
0
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);
}
예제 #6
0
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);
			}
		}
	}
}
예제 #7
0
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;
}
예제 #8
0
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);
        }
    }
}
예제 #10
0
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 );
}
예제 #11
0
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);
}
예제 #12
0
파일: map.cpp 프로젝트: brun123/otclient
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);
                }
            }
        }
    }
}
예제 #13
0
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);
	}
}
예제 #14
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;
}
예제 #15
0
//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
}
예제 #16
0
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
}