Ejemplo n.º 1
0
int Graph::nodeDist(int id1, int id2, int t, int &dist)
{
	int x1, x2, y1, y2;
	if(nodePos(id1, t, x1, y1) && nodePos(id2, t, x2, y2))
	{
		dist = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
		return 1;
	}
	return 0;
}
Ejemplo n.º 2
0
void SceneManager::updateQueuesRec( const Frustum &frustum1, const Frustum *frustum2, bool sorted,
								    SceneNode &node, bool lightQueue, bool renderableQueue )
{
	if( !node._active ) return;
	
	if( node._type == SceneNodeTypes::Group )
	{
		// LOD
		Vec3f nodePos( node._absTrans.c[3][0], node._absTrans.c[3][1], node._absTrans.c[3][2] );
		float dist = (nodePos - frustum1.getOrigin()).length();
		
		GroupNode *gn = (GroupNode *)&node;
		if( dist < gn->_minDist || dist >= gn->_maxDist ) return;
	}
	else if( lightQueue && node._type == SceneNodeTypes::Light )
	{
		_lightQueue.push_back( &node );
	}
	else if( renderableQueue && node._renderable )
	{
		if( node._type == SceneNodeTypes::Emitter )
		{
			// Emitters are a special case since we have to use their local bounding box
			// If the emitter is transformed particle positions don't change
			if( !frustum1.cullBox( *node.getLocalBBox() ) &&
				(frustum2 == 0x0 || !frustum2->cullBox( *node.getLocalBBox() )) )
			{
				if( sorted )
				{
					node.tmpSortValue = nearestDistToAABB( frustum1.getOrigin(),
						node.getLocalBBox()->getMinCoords(), node.getLocalBBox()->getMaxCoords() );
				}
				_renderableQueue.push_back( &node );
			}
		}
		else
		{
			if( !frustum1.cullBox( node._bBox ) &&
				(frustum2 == 0x0 || !frustum2->cullBox( node._bBox )) )
			{
				if( sorted )
				{
					node.tmpSortValue = nearestDistToAABB( frustum1.getOrigin(),
						node._bBox.getMinCoords(), node._bBox.getMaxCoords() );
				}
				_renderableQueue.push_back( &node );
			}
		}
	}
			
	// Recurse over children
	for( uint32 i = 0, s = (uint32)node._children.size(); i < s; ++i )
	{
		updateQueuesRec( frustum1, frustum2, sorted, *node._children[i], lightQueue, renderableQueue );
	}
}
Ejemplo n.º 3
0
// Initialize a new geogram mesh corresponding to the current grid
void OctreeGrid::createMesh(
	GEO::Mesh &mesh, const Eigen::Vector3d &origin, const Eigen::Vector3d &spacing) const
{
	mesh.clear(false, false);

	// logger_debug("OctreeGrid", "createMesh(): Allocate vertices and cells");

	// Create the mesh of regular grid
	mesh.vertices.create_vertices(numNodes());
	for (int idx = 0; idx < numNodes(); ++idx) {
		Eigen::Vector3d pos = origin + nodePos(idx).cast<double>().cwiseProduct(spacing);
		mesh.vertices.point(idx) = GEO::vec3(pos[0], pos[1], pos[2]);
	}

	// Count num of leaf cells
	int numLeaves = 0;
	for (int c = 0; c < numCells(); ++c) {
		if (cellIsLeaf(c)) { ++numLeaves; }
	}
	GEO::index_t firstCube = mesh.cells.create_hexes(numLeaves);
	for (int q = 0, c = 0; q < numCells(); ++q) {
		if (!cellIsLeaf(q)) {
			continue;
		}
		Eigen::Vector3i diff[8] = {
			{0,0,0}, {1,0,0}, {0,1,0}, {1,1,0},
			{0,0,1}, {1,0,1}, {0,1,1}, {1,1,1}
		};
		for (GEO::index_t lv = 0; lv < 8; ++lv) {
			int cornerId = Cube::invDelta(diff[lv]);
			int v = cellCornerId(q, cornerId);
			mesh.cells.set_vertex(firstCube + c, lv, v);
		}
		++c;
	}

	// logger_debug("OctreeGrid", "createMesh(): Connecting cells");
	//GEO::Logger::out("OctreeGrid") << "Computing borders..." << std::endl;
	//mesh.cells.compute_borders();
	//GEO::Logger::out("OctreeGrid") << "Connecting cells..." << std::endl;
	//mesh.cells.connect();

	// logger_debug("OctreeGrid", "createMesh(): Creating attributes...");
	updateMeshAttributes(mesh);
}
Ejemplo n.º 4
0
//--------------------------------------------------------------
void testApp::setup(){
    
    cout << "-------------------oo" << endl;
    cout << "-------------------oo" << endl;
    
    ofSetFrameRate(30);
    ofSetVerticalSync(true);
    //ofEnableAlphaBlending();
    //ofEnableSmoothing();
    //ofSetCircleResolution(32);
    ofBackground(0);
    ofSetBackgroundAuto(true);
    
    //DirectoryUtils dirUtil;
    
    ofDirectory dir("");

    dir.listDir();
    

    cout << "FileCount: " << dir.numFiles() << endl;
    cout << "FilePath: " << dir.getPath(0) << endl;
    cout << "FilePath: " << dir.getAbsolutePath() << endl;
    cout << " " << endl;
    
    ofVec2f nodePos(10,50);
    ofVec2f nodeSize(200,17);
    
    for (int i = 0; i < dir.numFiles(); i++) {
        string filePath = dir.getAbsolutePath() + "/" + dir.getPath(i);
        files.push_back(filePath);
        cout << files[i] << endl;
        
        nodes.push_back(Node(nodePos, nodeSize, filePath));
        nodePos += ofVec2f(0,20);
        
    }

}
Ejemplo n.º 5
0
bool MWMechanics::AiWander::execute (const MWWorld::Ptr& actor)
{
    if(mDuration)
    {
        // End package if duration is complete or mid-night hits:
        MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
        if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
        {
            if(!mRepeat)
            {
                stopWalking(actor, mPathFinder);
                return true;
            }
            else
                mStartTime = currentTime;
        }
        else if(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())
        {
            if(!mRepeat)
            {
                stopWalking(actor, mPathFinder);
                return true;
            }
            else
                mStartTime = currentTime;
        }
    }

    ESM::Position pos = actor.getRefData().getPosition();

    if(!mStoredAvailableNodes)
    {
        mStoredAvailableNodes = true;
        mPathgrid =
            MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);

        mCellX = actor.getCell()->mCell->mData.mX;
        mCellY = actor.getCell()->mCell->mData.mY;

        if(!mPathgrid)
            mDistance = 0;
        else if(mPathgrid->mPoints.empty())
            mDistance = 0;

        if(mDistance)
        {
            mXCell = 0;
            mYCell = 0;
            if(actor.getCell()->mCell->isExterior())
            {
                mXCell = mCellX * ESM::Land::REAL_SIZE;
                mYCell = mCellY * ESM::Land::REAL_SIZE;
            }

            Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos);
            npcPos[0] = npcPos[0] - mXCell;
            npcPos[1] = npcPos[1] - mYCell;

            for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
            {
                Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY, mPathgrid->mPoints[counter].mZ);
                if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
                    mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
            }
            if(!mAllowedNodes.empty())
            {
                Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ);
                float closestNode = npcPos.squaredDistance(firstNodePos);
                unsigned int index = 0;
                for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
                {
                    Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY, mAllowedNodes[counterThree].mZ);
                    float tempDist = npcPos.squaredDistance(nodePos);
                    if(tempDist < closestNode)
                        index = counterThree;
                }
                mCurrentNode = mAllowedNodes[index];
                mAllowedNodes.erase(mAllowedNodes.begin() + index);
            }

            if(mAllowedNodes.empty())
                mDistance = 0;
        }
    }

    MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
    bool cellChange = actor.getCell()->mCell->mData.mX != mCellX || actor.getCell()->mCell->mData.mY != mCellY;

    if(actor.getCell()->mCell->mData.mX != player.getCell()->mCell->mData.mX)
    {
        int sideX = sgn(actor.getCell()->mCell->mData.mX - player.getCell()->mCell->mData.mX);
        // Check if actor is near the border of an inactive cell. If so, disable AiWander.
        // FIXME: This *should* pause the AiWander package instead of terminating it.
        if(sideX*(pos.pos[0] - actor.getCell()->mCell->mData.mX * ESM::Land::REAL_SIZE) > sideX * (ESM::Land::REAL_SIZE / 2.0 - 200)) 
        {
            MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
            return true;
        }
    }

    if(actor.getCell()->mCell->mData.mY != player.getCell()->mCell->mData.mY)
    {
        int sideY = sgn(actor.getCell()->mCell->mData.mY - player.getCell()->mCell->mData.mY);
        // Check if actor is near the border of an inactive cell. If so, disable AiWander.
        // FIXME: This *should* pause the AiWander package instead of terminating it.
        if(sideY*(pos.pos[1] - actor.getCell()->mCell->mData.mY * ESM::Land::REAL_SIZE) > sideY * (ESM::Land::REAL_SIZE / 2.0 - 200)) 
        {
            MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 0;
            return true;
        }
    }

    // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
    if(mDistance && (cellChange || (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY)))
        mDistance = 0;

    if(mChooseAction)
    {
        mPlayedIdle = 0;
        unsigned short idleRoll = 0;

        for(unsigned int counter = 1; counter < mIdle.size(); counter++)
        {
            unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter];
            unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier));
            if(randSelect < idleChance && randSelect > idleRoll)
            {
                mPlayedIdle = counter;
                idleRoll = randSelect;
            }
        }

        if(!mPlayedIdle && mDistance)
        {
            mChooseAction = false;
            mMoveNow = true;
        }
        else
        {
            // Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
            MWWorld::TimeStamp currentTime = MWBase::Environment::get().getWorld()->getTimeStamp();
            mStartTime = currentTime;
            playIdle(actor, mPlayedIdle + 1);
            mChooseAction = false;
            mIdleNow = true;
        }
    }

    if(mIdleNow)
    {
        if(!checkIdle(actor, mPlayedIdle + 1))
        {
            mPlayedIdle = 0;
            mIdleNow = false;
            mChooseAction = true;
        }
    }

    if(mMoveNow && mDistance)
    {
        if(!mPathFinder.isPathConstructed())
        {
            unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
            Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ);

            // Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
            ESM::Pathgrid::Point temp = mAllowedNodes[randNode];
            mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
            mAllowedNodes.push_back(mCurrentNode);
            mCurrentNode = temp;

            ESM::Pathgrid::Point dest;
            dest.mX = destNodePos[0] + mXCell;
            dest.mY = destNodePos[1] + mYCell;
            dest.mZ = destNodePos[2];

            ESM::Pathgrid::Point start;
            start.mX = pos.pos[0];
            start.mY = pos.pos[1];
            start.mZ = pos.pos[2];

            mPathFinder.buildPath(start,dest,mPathgrid,mXCell,mYCell);
            mWalking = true;
        }
    }

    if(mWalking)
    {
        float zAngle = mPathFinder.getZAngleToNext(pos.pos[0],pos.pos[1],pos.pos[2]);
        MWBase::Environment::get().getWorld()->rotateObject(actor,0,0,zAngle,false);
        MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;

        // Unclog path nodes by allowing the NPC to be a small distance away from the center. This way two NPCs can be
        // at the same path node at the same time and both will complete instead of endlessly walking into eachother:
        Ogre::Vector3 destNodePos(mCurrentNode.mX, mCurrentNode.mY, mCurrentNode.mZ);
        Ogre::Vector3 actorPos(actor.getRefData().getPosition().pos);
        actorPos[0] = actorPos[0] - mXCell;
        actorPos[1] = actorPos[1] - mYCell;
        float distance = actorPos.squaredDistance(destNodePos);

        if(distance < 1200 || mPathFinder.checkIfNextPointReached(pos.pos[0],pos.pos[1],pos.pos[2]))
        {
            stopWalking(actor, mPathFinder);
            mMoveNow = false;
            mWalking = false;
            mChooseAction = true;
        }
        
    }

    return false;
}
Ejemplo n.º 6
0
bool AiWander::execute (const MWWorld::Ptr& actor,float duration)
{
    if (actor.getClass().isNpc())
        actor.getClass().getNpcStats(actor).setDrawState(DrawState_Nothing);
    MWBase::World *world = MWBase::Environment::get().getWorld();
    if(mDuration)
    {
        // End package if duration is complete or mid-night hits:
        MWWorld::TimeStamp currentTime = world->getTimeStamp();
        if(currentTime.getHour() >= mStartTime.getHour() + mDuration)
        {
            if(!mRepeat)
            {
                stopWalking(actor);
                return true;
            }
            else
                mStartTime = currentTime;
        }
        else if(int(currentTime.getHour()) == 0 && currentTime.getDay() != mStartTime.getDay())
        {
            if(!mRepeat)
            {
                stopWalking(actor);
                return true;
            }
            else
                mStartTime = currentTime;
        }
    }

    ESM::Position pos = actor.getRefData().getPosition();

    if(!mStoredAvailableNodes)
    {
        mStoredAvailableNodes = true;
        mPathgrid = world->getStore().get<ESM::Pathgrid>().search(*actor.getCell()->mCell);

        mCellX = actor.getCell()->mCell->mData.mX;
        mCellY = actor.getCell()->mCell->mData.mY;

        if(!mPathgrid)
            mDistance = 0;
        else if(mPathgrid->mPoints.empty())
            mDistance = 0;

        if(mDistance)
        {
            mXCell = 0;
            mYCell = 0;
            if(actor.getCell()->mCell->isExterior())
            {
                mXCell = mCellX * ESM::Land::REAL_SIZE;
                mYCell = mCellY * ESM::Land::REAL_SIZE;
            }

            Ogre::Vector3 npcPos(actor.getRefData().getPosition().pos);
            npcPos[0] = npcPos[0] - mXCell;
            npcPos[1] = npcPos[1] - mYCell;

            for(unsigned int counter = 0; counter < mPathgrid->mPoints.size(); counter++)
            {
                Ogre::Vector3 nodePos(mPathgrid->mPoints[counter].mX, mPathgrid->mPoints[counter].mY,
                                      mPathgrid->mPoints[counter].mZ);
                if(npcPos.squaredDistance(nodePos) <= mDistance * mDistance)
                    mAllowedNodes.push_back(mPathgrid->mPoints[counter]);
            }
            if(!mAllowedNodes.empty())
            {
                Ogre::Vector3 firstNodePos(mAllowedNodes[0].mX, mAllowedNodes[0].mY, mAllowedNodes[0].mZ);
                float closestNode = npcPos.squaredDistance(firstNodePos);
                unsigned int index = 0;
                for(unsigned int counterThree = 1; counterThree < mAllowedNodes.size(); counterThree++)
                {
                    Ogre::Vector3 nodePos(mAllowedNodes[counterThree].mX, mAllowedNodes[counterThree].mY,
                                          mAllowedNodes[counterThree].mZ);
                    float tempDist = npcPos.squaredDistance(nodePos);
                    if(tempDist < closestNode)
                        index = counterThree;
                }
                mCurrentNode = mAllowedNodes[index];
                mAllowedNodes.erase(mAllowedNodes.begin() + index);
            }
        }
    }

    if(mAllowedNodes.empty())
        mDistance = 0;

    // Don't try to move if you are in a new cell (ie: positioncell command called) but still play idles.
    if(mDistance && (mCellX != actor.getCell()->mCell->mData.mX || mCellY != actor.getCell()->mCell->mData.mY))
        mDistance = 0;

    if(mChooseAction)
    {
        mPlayedIdle = 0;
        unsigned short idleRoll = 0;

        for(unsigned int counter = 0; counter < mIdle.size(); counter++)
        {
            unsigned short idleChance = mIdleChanceMultiplier * mIdle[counter];
            unsigned short randSelect = (int)(rand() / ((double)RAND_MAX + 1) * int(100 / mIdleChanceMultiplier));
            if(randSelect < idleChance && randSelect > idleRoll)
            {
                mPlayedIdle = counter+2;
                idleRoll = randSelect;
            }
        }

        if(!mPlayedIdle && mDistance)
        {
            mChooseAction = false;
            mMoveNow = true;
        }
        else
        {
            // Play idle animation and recreate vanilla (broken?) behavior of resetting start time of AIWander:
            MWWorld::TimeStamp currentTime = world->getTimeStamp();
            mStartTime = currentTime;
            playIdle(actor, mPlayedIdle);
            mChooseAction = false;
            mIdleNow = true;
        }
    }

    if(mIdleNow)
    {
        if(!checkIdle(actor, mPlayedIdle))
        {
            mPlayedIdle = 0;
            mIdleNow = false;
            mChooseAction = true;
        }
    }

    if(mMoveNow && mDistance)
    {
        if(!mPathFinder.isPathConstructed())
        {
            assert(mAllowedNodes.size());
            unsigned int randNode = (int)(rand() / ((double)RAND_MAX + 1) * mAllowedNodes.size());
            Ogre::Vector3 destNodePos(mAllowedNodes[randNode].mX, mAllowedNodes[randNode].mY, mAllowedNodes[randNode].mZ);

            ESM::Pathgrid::Point dest;
            dest.mX = destNodePos[0] + mXCell;
            dest.mY = destNodePos[1] + mYCell;
            dest.mZ = destNodePos[2];

            ESM::Pathgrid::Point start;
            start.mX = pos.pos[0];
            start.mY = pos.pos[1];
            start.mZ = pos.pos[2];

            mPathFinder.buildPath(start, dest, mPathgrid, mXCell, mYCell, false);

            if(mPathFinder.isPathConstructed())
            {
                // Remove this node as an option and add back the previously used node (stops NPC from picking the same node):
                ESM::Pathgrid::Point temp = mAllowedNodes[randNode];
                mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
                mAllowedNodes.push_back(mCurrentNode);
                mCurrentNode = temp;

                mMoveNow = false;
                mWalking = true;
            }
            // Choose a different node and delete this one from possible nodes because it is uncreachable:
            else
                mAllowedNodes.erase(mAllowedNodes.begin() + randNode);
        }
    }

    if(mWalking)
    {
        float zAngle = mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]);
        // TODO: use movement settings instead of rotating directly
        world->rotateObject(actor, 0, 0, zAngle, false);
        MWWorld::Class::get(actor).getMovementSettings(actor).mPosition[1] = 1;

        if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
        {
            stopWalking(actor);
            mMoveNow = false;
            mWalking = false;
            mChooseAction = true;
        }
    }

    return false;
}
double ClusteringCoefficient::sequentialAvgLocal(const Graph &G) {
    WARN("DEPRECATED: use centrality.LocalClusteringCoefficient and take average");
	std::vector<std::vector<node> > edges(G.upperNodeIdBound());

	// copy edges with edge ids
	G.parallelForNodes([&](node u) {
		edges[u].reserve(G.degree(u));
		G.forEdgesOf(u, [&](node _u, node v, edgeid eid) {
			edges[u].emplace_back(v);
		});
	});

	//Node attribute: marker
	std::vector<bool> nodeMarker(G.upperNodeIdBound(), false);

	//Edge attribute: triangle count
	std::vector<count> triangleCount(G.upperNodeIdBound(), 0);

	// bucket sort
	count n = G.numberOfNodes();
	std::vector<node> sortedNodes(n);
	{
		std::vector<index> nodePos(n + 1, 0);

		G.forNodes([&](node u) {
			++nodePos[n - G.degree(u)];
		});

		// exclusive prefix sum
		index tmp = nodePos[0];
		index sum = tmp;
		nodePos[0] = 0;

		for (index i = 1; i < nodePos.size(); ++i) {
			tmp = nodePos[i];
			nodePos[i] = sum;
			sum += tmp;
		}

		G.forNodes([&](node u) {
			sortedNodes[nodePos[n - G.degree(u)]++] = u;
		});
	}

	for (node u : sortedNodes) {
		//Mark all neighbors
		for (auto v : edges[u]) {
			nodeMarker[v] = true;
		}

		//For all neighbors: check for already marked neighbors.
		for (auto v : edges[u]) {
			for (auto w = edges[v].begin(); w != edges[v].end(); ++w) {
				// delete the edge to u as we do not need to consider it again.
				// the opposite edge doesn't need to be deleted as we will never again consider
				// outgoing edges of u as u cannot be reached anymore after the uv loop.
				if (*w == u) {
					// move last element to current position in order to avoid changing too much
					*w = edges[v].back();
					edges[v].pop_back();
					if (w == edges[v].end()) // break if we were at the last element already
						break;
				}

				if (nodeMarker[*w]) { // triangle found - count it!
					++triangleCount[u];
					++triangleCount[*w];
					++triangleCount[v];
				}
			}

			nodeMarker[v] = false; // all triangles with u and v have been counted already
		}
	}

	double coefficient = 0;
	count size = 0;
	G.forNodes([&](node u) {
		count d = G.degree(u);
		if (d > 1) {
			coefficient += triangleCount[u] * 2.0 / (d * (d - 1));
			size++;
		}
	});

	return coefficient / size;
}
Ejemplo n.º 8
0
void TMXLayer::updateTotalQuads()
{
    if(_quadsDirty)
    {
        Size tileSize = CC_SIZE_PIXELS_TO_POINTS(_tileSet->_tileSize);
        Size texSize = _tileSet->_imageSize;
        _tileToQuadIndex.clear();
        (*_totalQuads).resize(int(_layerSize.width * _layerSize.height)); //[CY MOD]
        (*_indices).resize(6 * int(_layerSize.width * _layerSize.height));  //[CY MOD]
        _tileToQuadIndex.resize(int(_layerSize.width * _layerSize.height),-1);
        _indicesVertexZOffsets.clear();
        
        int quadIndex = 0;
        for(int y = 0; y < _layerSize.height; ++y)
        {
            for(int x =0; x < _layerSize.width; ++x)
            {
                int tileIndex = getTileIndexByPos(x, y);
                int tileGID = _tiles[tileIndex];
                
                if(tileGID == 0) continue;
                
                _tileToQuadIndex[tileIndex] = quadIndex;
                
                auto& quad = (*_totalQuads)[quadIndex]; //[CY MOD]
                
                Vec3 nodePos(float(x), float(y), 0);
                _tileToNodeTransform.transformPoint(&nodePos);
                
                float left, right, top, bottom, z;
                
                z = getVertexZForPos(Vec2(x, y));
                auto iter = _indicesVertexZOffsets.find(z);
                if(iter == _indicesVertexZOffsets.end())
                {
                    _indicesVertexZOffsets[z] = 1;
                }
                else
                {
                    iter->second++;
                }
                // vertices
                if (tileGID & kTMXTileDiagonalFlag)
                {
                    left = nodePos.x;
                    right = nodePos.x + tileSize.height;
                    bottom = nodePos.y + tileSize.width;
                    top = nodePos.y;
                }
                else
                {
                    left = nodePos.x;
                    right = nodePos.x + tileSize.width;
                    bottom = nodePos.y + tileSize.height;
                    top = nodePos.y;
                }
                
                if(tileGID & kTMXTileVerticalFlag)
                    std::swap(top, bottom);
                if(tileGID & kTMXTileHorizontalFlag)
                    std::swap(left, right);
                
                if(tileGID & kTMXTileDiagonalFlag)
                {
                    // FIXME: not working correcly
                    quad.bl.vertices.x = left;
                    quad.bl.vertices.y = bottom;
                    quad.bl.vertices.z = z;
                    quad.br.vertices.x = left;
                    quad.br.vertices.y = top;
                    quad.br.vertices.z = z;
                    quad.tl.vertices.x = right;
                    quad.tl.vertices.y = bottom;
                    quad.tl.vertices.z = z;
                    quad.tr.vertices.x = right;
                    quad.tr.vertices.y = top;
                    quad.tr.vertices.z = z;
                }
                else
                {
                    quad.bl.vertices.x = left;
                    quad.bl.vertices.y = bottom;
                    quad.bl.vertices.z = z;
                    quad.br.vertices.x = right;
                    quad.br.vertices.y = bottom;
                    quad.br.vertices.z = z;
                    quad.tl.vertices.x = left;
                    quad.tl.vertices.y = top;
                    quad.tl.vertices.z = z;
                    quad.tr.vertices.x = right;
                    quad.tr.vertices.y = top;
                    quad.tr.vertices.z = z;
                }
                // texcoords
                Rect tileTexture = _tileSet->getRectForGID(tileGID);
                left   = (tileTexture.origin.x) / texSize.width;
                right  = (tileTexture.origin.x+tileTexture.size.width) / texSize.width;
                bottom = (tileTexture.origin.y)/ texSize.height;
                top = (tileTexture.origin.y+tileTexture.size.height) / texSize.height;
                
                quad.bl.texCoords.u = left;
                quad.bl.texCoords.v = bottom;
                quad.br.texCoords.u = right;
                quad.br.texCoords.v = bottom;
                quad.tl.texCoords.u = left;
                quad.tl.texCoords.v = top;
                quad.tr.texCoords.u = right;
                quad.tr.texCoords.v = top;
                
                quad.bl.colors = Color4B::WHITE;
                quad.br.colors = Color4B::WHITE;
                quad.tl.colors = Color4B::WHITE;
                quad.tr.colors = Color4B::WHITE;
                
                ++quadIndex;
            }
        }
        
        int offset = 0;
        for(auto iter = _indicesVertexZOffsets.begin(); iter != _indicesVertexZOffsets.end(); ++iter)
        {
            std::swap(offset, iter->second);
            offset += iter->second;
        }
        updateVertexBuffer();
        
        _quadsDirty = false;
    }
}