void ParticleProducer::initialize()
{
    assert(!initialized);
    int totalSize = (getParticleSize() / 8) * 8 + 8 * (getParticleSize() % 8 != 0);
    for (unsigned int i = 0; i < layers.size(); ++i) {
        layers[i]->offset = totalSize;
        totalSize += layers[i]->getParticleSize();
    }

    storage->initCpuStorage(totalSize);
    for (unsigned int i = 0; i < layers.size(); ++i) {
        layers[i]->initialize();
    }
    initialized = true;
}
    //=====-----=======---------=========---------==========---------=========----------=============
    void ParticleSet::drawParticles( SpriteBatch& sb, const std::vector<TexturePtr> textures, const Color& color, const int layer )
	{
		for(int i = 0; i <= mHighestLiveIndex; ++i)
		{
			if(!mParticles[i].mAlive)
			{
				continue;
			}
			
			if (mParticles[i].mLifetime == -1.0f) 
			{
                Color finalColor( color );
                finalColor *= mParticles[i].mAlphaMultiplier;
				sb.drawQuad(layer, textures[mParticles[i].mTextureIndex], mParticles[i].mPosition + VectorTools::rotateVector(mParticles[i].mOffset, Walaber::degToRad(mParticles[i].mAngleDeg)), Walaber::degToRad(mParticles[i].mAngleDeg), mParticles[i].mSize, finalColor);
			}
			else 
			{	
				Color fadeOut = _getParticleColor(&mParticles[i], color); // color * lerp(0.0f, 1.0f, mParticles[i].mLifetime / mParticles[i].mFadeLength);
                
				sb.drawQuad(layer, textures[mParticles[i].mTextureIndex], mParticles[i].mPosition + VectorTools::rotateVector(mParticles[i].mOffset, Walaber::degToRad(mParticles[i].mAngleDeg)), Walaber::degToRad(mParticles[i].mAngleDeg), getParticleSize(i), fadeOut);
			}
		}
	}
	//=====-----=======---------=========---------==========---------=========----------=============
    void ParticleSet::drawParticles( SpriteBatch& sb, const TexturePtr texture, const Color& color, const int layer, const float sizeFactor, bool doFade )
	{
		for(int i = 0; i <= mHighestLiveIndex; ++i)
		{
			if(!mParticles[i].mAlive)
			{
				continue;
			}
			
			if (mParticles[i].mLifetime == -1.0f) 
			{
                Color finalColor( color );
                finalColor *= mParticles[i].mAlphaMultiplier;
				sb.drawQuad(layer, texture, mParticles[i].mPosition + VectorTools::rotateVector(mParticles[i].mOffset, Walaber::degToRad(mParticles[i].mAngleDeg)), Walaber::degToRad(mParticles[i].mAngleDeg), mParticles[i].mSize * sizeFactor, finalColor);
			}
			else 
			{
				Color finalCol = color;
				
				if (doFade)
					finalCol = _getParticleColor(&mParticles[i], color); // color * lerp(0.0f, 1.0f, mParticles[i].mLifetime / mParticles[i].mFadeLength);
                
				sb.drawQuad(layer, texture, mParticles[i].mPosition + VectorTools::rotateVector(mParticles[i].mOffset, Walaber::degToRad(mParticles[i].mAngleDeg)), Walaber::degToRad(mParticles[i].mAngleDeg), getParticleSize(i) * sizeFactor, finalCol);
			}
		}
	}
    CrossCorrelationMarkerDetector::CrossCorrelationMarkerDetector(Framework *framework, const Vec2ui &projectionResolution, GPUMapped<Image> *particlePattern)
        : ParticleDetectorInterface(particlePattern->getResolution(), true, false)
        , activeMarkerPatternBuffer(particlePattern)
        , ownInputPattern(false)
        , projectionResolution(projectionResolution)
    {
        this->isOperatingInBrightFieldMode = true;

        this->stubSource            = new GPUMapped<Image>(framework->getOpenCLStack(), projectionResolution);
        this->nccOperator           = new CrosscorrelationOperator(framework, stubSource, activeMarkerPatternBuffer);
        this->thresholdOperator     = new ThresholdKernel(framework, nccOperator->getOutput());
        this->localMaxOperator      = new LocalMaximumSimpleKernel(framework, thresholdOperator->getOutput(), activeMarkerPatternBuffer->getResolution());

        structElement               = new GPUMapped<Image>(framework->getOpenCLStack(), StructuringElementGenerator::generateDiamondElement());
        structElement->takeOwnershipOfObjectOnCPU();

        this->closingOperator       = new ClosingOperator(framework, thresholdOperator->getOutput(), structElement);
        this->borderSegmentator     = new BorderSegmentKernel(framework, closingOperator->getOutput());
        this->circularityRejector   = new CircularityRejectionKernel(framework, localMaxOperator->getOutput(), borderSegmentator->getOutput(), getParticleSize());

        this->borderSegmentator->setUsingEightNeighbors(true);
    }