//--------------------------------------------------------
void CRemoveBKSprite::draw(void)
{
	CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
	CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");

	CC_NODE_DRAW_SETUP();

	// 启用attributes变量输入,顶点坐标,纹理坐标,颜色
	ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
	ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);

	m_pShaderProgram->use();
	m_pShaderProgram->setUniformsForBuiltins();

	// 绑定纹理到纹理槽0
	ccGLBindTexture2D(m_pobTexture->getName());

	long offset = (long)&m_sQuad;
	// vertex
	int diff = offsetof( ccV3F_C4B_T2F, vertices);
	glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, sizeof(m_sQuad.bl), (void*) (offset + diff));
	// texCoods
	diff = offsetof( ccV3F_C4B_T2F, texCoords);
	glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(m_sQuad.bl), (void*)(offset + diff));
	// color
	diff = offsetof( ccV3F_C4B_T2F, colors);
	glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(m_sQuad.bl), (void*)(offset + diff));

	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	CHECK_GL_ERROR_DEBUG();

	CC_INCREMENT_GL_DRAWS(1);
	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}
Beispiel #2
0
// override visit
// don't call visit on it's children
void SpriteBatchNode::visit(void)
{
    CC_PROFILER_START_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

    // CAREFUL:
    // This visit is almost identical to CocosNode#visit
    // with the exception that it doesn't call visit on it's children
    //
    // The alternative is to have a void Sprite#visit, but
    // although this is less maintainable, is faster
    //
    if (! _visible)
    {
        return;
    }

    kmGLPushMatrix();

    sortAllChildren();
    transform();

    draw();

    kmGLPopMatrix();
    setOrderOfArrival(0);

    CC_PROFILER_STOP_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");
}
void HueSprite::draw()
{

    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
        
	CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
        
	//CC_NODE_DRAW_SETUP();
	ccGLEnable( m_eGLServerState );
        
	ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );
        
	m_shader->use();
    m_shader->setUniformsForBuiltins();


	if (m_pobTexture != NULL)
	{
		//ccGLBindTexture2D( m_texure1->getName());
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, m_pobTexture->getName());
	}
	else
	{
		ccGLBindTexture2D(0);
	}


	glUniformMatrix3fv(m_loc_hue, 1, GL_FALSE, (GLfloat*)&m_mat);

	//
	// Attributes
	//
	ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
        
#define kQuadSize sizeof(m_sQuad.bl)
	long offset = (long)&m_sQuad;
        
	// vertex
	int diff = offsetof( ccV3F_C4B_T2F, vertices);
	glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
        
	// texCoods
	diff = offsetof( ccV3F_C4B_T2F, texCoords);
	glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
        
	// color
	diff = offsetof( ccV3F_C4B_T2F, colors);
	glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
        
        
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
	CHECK_GL_ERROR_DEBUG();
        
	CC_INCREMENT_GL_DRAWS(1);
        
	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}
Beispiel #4
0
/**
 * 绘制
 */
void MapCoordLine::draw(void)
{
	CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");

	CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");

	CC_NODE_DRAW_SETUP();

	ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );

	if (m_pobTexture != NULL)
	{
		ccGLBindTexture2D( m_pobTexture->getName() );
	}
	else
	{
		ccGLBindTexture2D(0);
	}

	//
	// Attributes
	//

	ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );

	#define kQuadSize sizeof(m_sQuad.bl)
	if (points.size())
	{
		long offset = (long)&points[0];

		// vertex
		int diff = offsetof( ccV3F_C4B_T2F, vertices);
		glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

		// texCoods
		diff = offsetof( ccV3F_C4B_T2F, texCoords);
		glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

		// color
		diff = offsetof( ccV3F_C4B_T2F, colors);
		glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


		glDrawArrays(GL_LINES, 0, points.size());
	}
	CHECK_GL_ERROR_DEBUG();

	CC_INCREMENT_GL_DRAWS(1);

	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}
void CCCatmullRomSprite::draw() {
    // at least we need two points
    if(m_controlPoints.getCount() < 2)
        return;
    
	// build atlas
	if(m_dirty) {
		updateAtlas();
		m_dirty = false;
	}
	
	// profile start
	CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCCatmullRomSprite - draw");
	
	// setup
    CC_NODE_DRAW_SETUP();
	
	// blend func
	ccBlendFunc bf = m_sprite->getBlendFunc();
    ccGLBlendFunc(bf.src, bf.dst);
	
    // draw
	if(m_atlas) {
        if(m_allVisible) {
            m_atlas->drawQuadsEx();
        } else {
            int startIndex = 0;
            int sc = getSegmentCount();
            for(int i = 0; i < sc; i++) {
                bool visible = isSegmentVisible(i);
                if(!visible) {
                    int endIndex = m_segmentQuadIndices[i];
                    m_atlas->drawNumberOfQuadsEx(endIndex - startIndex, startIndex);
                    startIndex = m_segmentQuadIndices[i + 1];
                }
            }
            
            // last
            if(m_atlas->getTotalQuads() > startIndex) {
                m_atlas->drawNumberOfQuadsEx(m_atlas->getTotalQuads() - startIndex, startIndex);
            }
        }
    }
	
	// profile end
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCCatmullRomSprite - draw");
}
void IsometryNode::visit()
{
    //setPosition(CCPointMake(0, 500));
    //CCNode::visit();
    //Stats();
    if(getShaderProgram() == nullptr)
    {
        setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColor));
    }
    
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");
    
    // CAREFUL:
    // This visit is almost identical to CocosNode#visit
    // with the exception that it doesn't call visit on it's children
    //
    // The alternative is to have a void CCSprite#visit, but
    // although this is less maintainable, is faster
    //
    if (! m_bVisible)
    {
        return;
    }
    
    kmGLPushMatrix();
    
    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->beforeDraw();
        transformAncestors();
    }
    
    sortAllChildren();
    transform();

    draw();
    
    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->afterDraw(this);
    }
    
    kmGLPopMatrix();
    setOrderOfArrival(0);
    
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");
}
void ShaderSprite::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");

    // CCAssert(, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");

    CC_NODE_DRAW_SETUP();

    //
    // 启用attributes变量输入,顶点坐标,纹理坐标,颜色
    //
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
    ccGLBlendFunc(this->getBlendFunc().src, this->getBlendFunc().dst);

    this->getShaderProgram()->use();
    this->getShaderProgram()->setUniformsForBuiltins();

    // 绑定纹理到纹理槽0
    ccGLBindTexture2D(this->getTexture()->getName());



#define kQuadSize sizeof(this->_quad.bl)
    long offset = (long)&this->_quad;

    // vertex
    int diff = offsetof( ccV3F_C4B_T2F, vertices);
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

    // texCoods
    diff = offsetof( ccV3F_C4B_T2F, texCoords);
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

    // color
    diff = offsetof( ccV3F_C4B_T2F, colors);
    glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    CHECK_GL_ERROR_DEBUG();

    CC_INCREMENT_GL_DRAWS(1);
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}
Beispiel #8
0
void CABatchView::visit(void)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, "CABatchView - visit");

    CC_RETURN_IF(!m_bVisible);
    
    kmGLPushMatrix();
    sortAllSubview();
    transform();

    draw();

    kmGLPopMatrix();
    setOrderOfArrival(0);

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, "CABatchView - visit");

}
// override visit
// don't call visit on it's children
// 是基类CCNode虚函数,是每帧会被调用到的函数。
void CCSpriteBatchNode::visit(void)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

    // CAREFUL:
    // This visit is almost identical to CocosNode#visit
    // with the exception that it doesn't call visit on it's children
    //
    // The alternative is to have a void CCSprite#visit, but
    // although this is less maintainable, is faster
    //
	// 如果不显示,直接返回
    if (! m_bVisible)
    {
        return;
    }
	//矩阵压栈,保存渲染此结点前的所有OpenGL所需矩阵的值 
    kmGLPushMatrix();

    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->beforeDraw();
        transformAncestors();
    }

    sortAllChildren();
	//矩阵变量
    transform();
	//基类CCNode虚函数,用于实现当前CCNode的绘制
    draw();

    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->afterDraw(this);
    }
	//矩阵出栈。恢复渲染此结点前的所有OpenGL所需矩阵的值
    kmGLPopMatrix();
    setOrderOfArrival(0);

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

}
Beispiel #10
0
// override visit
// don't call visit on it's children
void CCSpriteBatchNode::visit(void)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

    // CAREFUL:
    // This visit is almost identical to CocosNode#visit
    // with the exception that it doesn't call visit on it's children
    //
    // The alternative is to have a void CCSprite#visit, but
    // although this is less maintainable, is faster
    //
    if (! m_bVisible)
    {
        return;
    }

    kmGLPushMatrix();

    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->beforeDraw();
        transformAncestors();
    }

    sortAllChildren();
    transform();

    draw();

    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->afterDraw(this);
    }

    kmGLPopMatrix();

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

}
// override visit
// don't call visit on it's children
void SpriteBatchNode::visit(Renderer *renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
    CC_PROFILER_START_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");

    // CAREFUL:
    // This visit is almost identical to CocosNode#visit
    // with the exception that it doesn't call visit on it's children
    //
    // The alternative is to have a void Sprite#visit, but
    // although this is less maintainable, is faster
    //
    if (! _visible)
    {
        return;
    }

    sortAllChildren();

    uint32_t flags = processParentFlags(parentTransform, parentFlags);

    if (isVisitableByVisitingCamera())
    {
        // IMPORTANT:
        // To ease the migration to v3.0, we still support the Mat4 stack,
        // but it is deprecated and your code should not rely on it
        Director* director = Director::getInstance();
        director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
        director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
        
        draw(renderer, _modelViewTransform, flags);
        
        director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
        // FIX ME: Why need to set _orderOfArrival to 0??
        // Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
        //    setOrderOfArrival(0);
        
        CC_PROFILER_STOP_CATEGORY(kProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit");
    }
}
void BlurSprite::draw()
{

    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
        
	CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
        
	//CC_NODE_DRAW_SETUP();
	ccGLEnable( m_eGLServerState );

	ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );

	// 水平方向blur 
	m_frameTexture->clear(0.f, 0.f, 0.f, 0.f);
	m_frameTexture->begin();
	{

		m_shader->use();
		m_shader->setUniformsForBuiltins();

		glUniform2f(m_location_pix_size, 1.f/m_tex_size.width, 0);

		if (m_pobTexture != NULL)
		{
			ccGLBindTexture2D(m_pobTexture->getName());
		}
		else
		{
			ccGLBindTexture2D(0);
		}


		//
		// Attributes
		//
		ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );

#define kQuadSize sizeof(m_sQuad.bl)
		long offset = (long)&m_sQuad;

		// vertex
		int diff = offsetof( ccV3F_C4B_T2F, vertices);
		glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

		// texCoods
		diff = offsetof( ccV3F_C4B_T2F, texCoords);
		glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

		// color
		diff = offsetof( ccV3F_C4B_T2F, colors);
		glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		CHECK_GL_ERROR_DEBUG();

	}
	m_frameTexture->end();

	// 垂直方向blur
	CCTexture2D* rt = m_frameTexture->getSprite()->getTexture();
#if CC_DEBUG
	m_frameTexture2->clear(0.f, 0.f, 0.f, 0.f);
	m_frameTexture2->begin();
#endif
	{
		m_shader->use();
		m_shader->setUniformsForBuiltins();

		glUniform2f(m_location_pix_size, 0, 1.f/m_tex_size.height);

		if ( rt != NULL)
		{
			ccGLBindTexture2D(rt->getName());
		}
		else
		{
			ccGLBindTexture2D(0);
		}


		//
		// Attributes
		//
		ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );

#define kQuadSize sizeof(m_sQuad.bl)
		long offset = (long)&m_sQuad;

		// vertex
		int diff = offsetof( ccV3F_C4B_T2F, vertices);
		glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

		// texCoods
		diff = offsetof( ccV3F_C4B_T2F, texCoords);
		glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

		// color
		diff = offsetof( ccV3F_C4B_T2F, colors);
		glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


		glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

		CHECK_GL_ERROR_DEBUG();
	}
#if CC_DEBUG
	m_frameTexture2->end();
	m_frameTexture2->saveToFile("blur_complete.png");
#endif

	CC_INCREMENT_GL_DRAWS(1);
        
	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
}
Beispiel #13
0
void NParticleSystemQuad::update(float dt) {
    CC_PROFILER_START_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");

    if (_isActive && _emissionRate)
    {
        float rate = 1.0f / _emissionRate;
        //issue #1201, prevent bursts of particles, due to too high emitCounter
        if (_particleCount < _totalParticles)
        {
            _emitCounter += dt;
        }

        while (_particleCount < _totalParticles && _emitCounter > rate)
        {
            this->addParticle();
            _emitCounter -= rate;
        }

        _elapsed += dt;
        if (_duration != -1 && _duration < _elapsed)
        {
            this->stopSystem();
        }
    }

    _particleIdx = 0;

    Vec2 currentPosition = Vec2::ZERO;
    if (_positionType == PositionType::FREE)
    {
        currentPosition = this->convertToWorldSpace(Vec2::ZERO);
    }
    else if (_positionType == PositionType::RELATIVE)
    {
        currentPosition = _position;
    }

    {
        while (_particleIdx < _particleCount)
        {
            tParticle *p = &_particles[_particleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0)
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (_emitterMode == Mode::GRAVITY)
                {
                    Vec2 tmp, radial, tangential;

                    radial = Vec2::ZERO;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = p->pos.getNormalized();
                    }
                    tangential = radial;
                    radial = radial * p->modeA.radialAccel;

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = tangential * p->modeA.tangentialAccel;

                    // (gravity + radial + tangential) * dt
                    tmp = radial + tangential + modeA.gravity;
                    tmp = tmp * dt;
                    p->modeA.dir = p->modeA.dir + tmp;

                    // this is cocos2d-x v3.0
                    //                    if (_configName.length()>0 && _yCoordFlipped != -1)

                    // this is cocos2d-x v3.0
                    tmp = p->modeA.dir * dt * _yCoordFlipped;
                    p->pos = p->pos + tmp;
                }

                // Mode B: radius movement
                else
                {
                    // Update the angle and radius of the particle.
                    p->modeB.angle += p->modeB.degreesPerSecond * dt;
                    p->modeB.radius += p->modeB.deltaRadius * dt;

                    p->pos.x = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y *= _yCoordFlipped;
                }

                // color
                p->color.r += (p->deltaColor.r * dt);
                p->color.g += (p->deltaColor.g * dt);
                p->color.b += (p->deltaColor.b * dt);
                p->color.a += (p->deltaColor.a * dt);

                // size
                p->size += (p->deltaSize * dt);
                p->size = MAX( 0, p->size );

                // angle
                p->rotation += (p->deltaRotation * dt);

                //
                // update values in quad
                //

                Vec2    newPos;

                if (_positionType == PositionType::FREE || _positionType == PositionType::RELATIVE)
                {
                    Vec2 diff = currentPosition - p->startPos;
                    newPos = p->pos - diff;
                }
                else
                {
                    newPos = p->pos;
                }

                // translate newPos to correct position, since matrix transform isn't performed in batchnode
                // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
                if (_batchNode)
                {
                    newPos.x+=_position.x;
                    newPos.y+=_position.y;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++_particleIdx;
            }
            else
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( _particleIdx != _particleCount-1 )
                {
                    _particles[_particleIdx] = _particles[_particleCount-1];
                }
                if (_batchNode)
                {
                    //disable the switched particle
                    _batchNode->disableParticle(_atlasIndex+currentIndex);

                    //switch indexes
                    _particles[_particleCount-1].atlasIndex = currentIndex;
                }


                --_particleCount;

                if( _particleCount == 0 && _isAutoRemoveOnFinish )
                {

                    this->unscheduleUpdate();
                    _parent->removeChild(this, true);
                    // 親から remove されるときにコールバック関数を呼ぶ
                    if (onFinishListener) {
                        onFinishListener(this);
                    }
                    return;
                }
            }
        } //while
        _transformSystemDirty = false;
    }

    // only update gl buffer when visible
    if (_visible && ! _batchNode)
    {
        postStep();
    }

    CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");
}
void SpriteMask::draw()
{
	if (!_isSetMask)   //沒有設定就直接用預設方法
	{
		CCSprite::draw();
		return;
	}

	CC_PROFILER_START_CATEGORY(kProfilerCategorySprite, "CCSprite - draw");

	CCASSERT(!_batchNode, "If Sprite is being rendered by SpriteBatchNode, Sprite#draw SHOULD NOT be called");

	CC_NODE_DRAW_SETUP();

	GL::blendFunc(_blendFunc.src, _blendFunc.dst);

	GL::bindTexture2D(_texture->getName());
	GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);

	if (_texture != NULL) {
		ccGLBindTexture2D(_texture->getName());
	} else {
		ccGLBindTexture2D(0);
	}
	
	//mask 設定 設定使用mask貼圖
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, _maskTexture->getName());
	glUniform1i(_maskLocation, 1);
	glUniform2f(_offsetLocation, offsetWithPosition.x, offsetWithPosition.y);

#define kQuadSize sizeof(_quad.bl)
#ifdef EMSCRIPTEN
	long offset = 0;
	setGLBufferData(&_quad, 4 * kQuadSize, 0);
#else
	long offset = (long)&_quad;
#endif // EMSCRIPTEN

	// vertex
	int diff = offsetof(V3F_C4B_T2F, vertices);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

	// texCoods
	diff = offsetof(V3F_C4B_T2F, texCoords);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

	// color
	diff = offsetof(V3F_C4B_T2F, colors);
	glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	CHECK_GL_ERROR_DEBUG();


#if CC_SPRITE_DEBUG_DRAW == 1
	// draw bounding box
	Point vertices[4] = {
		Point(_quad.tl.vertices.x, _quad.tl.vertices.y),
		Point(_quad.bl.vertices.x, _quad.bl.vertices.y),
		Point(_quad.br.vertices.x, _quad.br.vertices.y),
		Point(_quad.tr.vertices.x, _quad.tr.vertices.y),
	};
	ccDrawPoly(vertices, 4, true);
#elif CC_SPRITE_DEBUG_DRAW == 2
	// draw texture box
	Size s = this->getTextureRect().size;
	Point offsetPix = this->getOffsetPosition();
	Point vertices[4] = {
		Point(offsetPix.x, offsetPix.y), Point(offsetPix.x + s.width, offsetPix.y),
		Point(offsetPix.x + s.width, offsetPix.y + s.height), Point(offsetPix.x, offsetPix.y + s.height)
	};
	ccDrawPoly(vertices, 4, true);
#endif // CC_SPRITE_DEBUG_DRAW

	CC_INCREMENT_GL_DRAWS(1);

	glActiveTexture(GL_TEXTURE0);  //must set to texture0

	CC_PROFILER_STOP_CATEGORY(kProfilerCategorySprite, "CCSprite - draw");
}
Beispiel #15
0
void YUVSprite::draw()
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "YUVSprite - draw");
    
    CCAssert(!m_pobBatchNode, "If YUVSprite is being rendered by CCSpriteBatchNode, YUVSprite#draw SHOULD NOT be called");
   // CC_NODE_DRAW_SETUP();
    ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );

    if(_prog){
        _prog->use();
        _prog->setUniformsForBuiltins();
    }
    if(textureDone){
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, id_y);
        glUniform1i(textureUniformY, 0);
        
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, id_u);
        glUniform1i(textureUniformU, 1);
        
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, id_v);
        glUniform1i(textureUniformV, 2);
        
        glUniform1f(borderUniformY,_border[0]);
        glUniform1f(borderUniformU,_border[1]);
        glUniform1f(borderUniformV,_border[2]);
    }
    //ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
    
#define kQuadSize sizeof(m_sQuad.bl)
#ifdef EMSCRIPTEN
    long offset = 0;
    setGLBufferData(&m_sQuad, 4 * kQuadSize, 0);
#else
    long offset = (long)&m_sQuad;
#endif // EMSCRIPTEN
    CHECK_GL_ERROR_DEBUG();
    
    GLfloat square[8];
    CCSize s = this->getTextureRect().size;
    CCPoint offsetPix = this->getOffsetPosition();
    
    square[0] = offsetPix.x;
    square[1] = offsetPix.y;
    
    square[2] = offsetPix.x+s.width;
    square[3] = offsetPix.y;
    
    square[6] = offsetPix.x+s.width;
    square[7] = offsetPix.y+s.height;
    
    square[4] = offsetPix.x;
    square[5] = offsetPix.y+s.height;

    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, square);
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    
    glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, coordVertices);
    glEnableVertexAttribArray(ATTRIB_TEXTURE);

    /*
    // vertex
    int diff = offsetof( ccV3F_C4B_T2F, vertices);
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
    
    // texCoods
    diff = offsetof( ccV3F_C4B_T2F, texCoords);
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
    
    // color
    diff = offsetof( ccV3F_C4B_T2F, colors);
    glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
    */
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    CHECK_GL_ERROR_DEBUG();
#if CC_SPRITE_DEBUG_DRAW == 1
    // draw bounding box
    CCPoint vertices[4]={
        ccp(m_sQuad.tl.vertices.x,m_sQuad.tl.vertices.y),
        ccp(m_sQuad.bl.vertices.x,m_sQuad.bl.vertices.y),
        ccp(m_sQuad.br.vertices.x,m_sQuad.br.vertices.y),
        ccp(m_sQuad.tr.vertices.x,m_sQuad.tr.vertices.y),
    };
    ccDrawPoly(vertices, 4, true);
#elif CC_SPRITE_DEBUG_DRAW == 2
    // draw texture box
    CCSize s = this->getTextureRect().size;
    CCPoint offsetPix = this->getOffsetPosition();
    CCPoint vertices[4] = {
        ccp(offsetPix.x,offsetPix.y), ccp(offsetPix.x+s.width,offsetPix.y),
        ccp(offsetPix.x+s.width,offsetPix.y+s.height), ccp(offsetPix.x,offsetPix.y+s.height)
    };
    ccDrawPoly(vertices, 4, true);
#endif // CC_SPRITE_DEBUG_DRAW
    CC_INCREMENT_GL_DRAWS(1);
    
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "YUVSprite - draw");
}
Beispiel #16
0
void Live2dXSprite::draw()
{
    if(!m_pobTexture)
    {
        return;
    }
    if(m_isAnimation)
    {
        cc_timeval nowTime;
        CCTime::gettimeofdayCocos2d(&nowTime, NULL);
        float deltime = (float)(nowTime.tv_sec - m_nowTime.tv_sec) + (float)(nowTime.tv_usec - m_nowTime.tv_usec)/1000000.0f;
        m_nowTime = nowTime;
        animationUpdate(deltime);
//        animationUpdate(1/30.0f);
    }
#define Live2dX_Vertex_Size sizeof(Live2dX_Vertex)
#define Live2dX_UV_Size sizeof(Live2dX_UV)
#define Live2dX_Color_Size sizeof(Live2dX_Color)
    
#ifndef __QT__
    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
    
    CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
    
    CC_NODE_DRAW_SETUP();
    
    ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );
    
    ccGLBindTexture2D( m_pobTexture->getName() );
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );

    
    // vertex
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, Live2dX_Vertex_Size, (void*)m_nowVertex.data());
    
    // texCoods
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, Live2dX_UV_Size, (void*)m_orginUV.data());
    
    // color
    glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, Live2dX_Color_Size, (void*)m_orginColor.data());
    
    
    glDrawArrays(GL_TRIANGLES, 0, (int)m_nowVertex.size());
    
    CHECK_GL_ERROR_DEBUG();
    
    CC_INCREMENT_GL_DRAWS(1);
    
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");
#else
    
    glTranslatef(-0.5f,0,0);
    glEnable(GL_BLEND);
    
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
    glBindTexture(GL_TEXTURE_2D,m_pobTexture->m_name);
    
    for(int i = 0; i < m_nowVertex.size();i+=3)
    {
        float a,b;
        glBegin(GL_TRIANGLES);
        glColor4f(1,1,1,1);
        glTexCoord2f(m_orginUV[i].u,1-m_orginUV[i].v);
        a = m_nowVertex[i].x * 2 / m_baseSize.width - 1;
        b = m_nowVertex[i].y * 2 / m_baseSize.height-1;
        glVertex3f(a,b,0);
        glColor4f(1,1,1,1);
        glTexCoord2f(m_orginUV[i+1].u,1-m_orginUV[i+1].v);
        a = m_nowVertex[i+1].x * 2 / m_baseSize.width - 1;
        b = m_nowVertex[i+1].y * 2 / m_baseSize.height-1;
        glVertex3f(a,b,0);
        glColor4f(1,1,1,1);
        glTexCoord2f(m_orginUV[i+2].u,1-m_orginUV[i+2].v);
        a = m_nowVertex[i+2].x * 2 / m_baseSize.width - 1;
        b = m_nowVertex[i+2].y * 2 / m_baseSize.height-1;
        glVertex3f(a,b,0);
        glColor4f(1,1,1,1);
        glEnd();
    }
#endif
}
Beispiel #17
0
void CCSquirmAnimNode::draw()
{
	CCAssert(m_pobTexture != 0 && m_maskTexture != 0, "CCSquirmAnimNode::draw(), textures mustn't be null!");
	CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "CCSprite - draw");

	// 如果顶点数据需要刷新,就刷新之
	if(m_vertices_dirty)
	{
		rebuildVertices();
	}

	CC_NODE_DRAW_SETUP();

	ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );

	ccGLBindTexture2DN(0, m_pobTexture->getName());
	ccGLBindTexture2DN(1, m_maskTexture->getName());

	//
	// Attributes
	//

	ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTexTex );

#define kQuadSize sizeof(m_sQuad.bl)
	long offset = (long)&m_sQuad;

	// vertex
	int diff = offsetof( ccV3F_C4B_T2Fx2, vertices);
	glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));

	// texCoods
	diff = offsetof( ccV3F_C4B_T2Fx2, texCoords);
	glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

	diff = offsetof(ccV3F_C4B_T2Fx2, texCoords1);
	glVertexAttribPointer(kCCVertexAttrib_TexCoords1, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));

	// color
	diff = offsetof( ccV3F_C4B_T2Fx2, colors);
	glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));


	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

	CHECK_GL_ERROR_DEBUG();


#if CC_SPRITE_DEBUG_DRAW == 1
	// draw bounding box
	CCPoint vertices[4]={
		ccp(m_sQuad.tl.vertices.x,m_sQuad.tl.vertices.y),
		ccp(m_sQuad.bl.vertices.x,m_sQuad.bl.vertices.y),
		ccp(m_sQuad.br.vertices.x,m_sQuad.br.vertices.y),
		ccp(m_sQuad.tr.vertices.x,m_sQuad.tr.vertices.y),
	};
	ccDrawPoly(vertices, 4, true);
#elif CC_SPRITE_DEBUG_DRAW == 2
	// draw texture box
	CCSize s = this->getTextureRect().size;
	CCPoint offsetPix = this->getOffsetPosition();
	CCPoint vertices[4] = {
		ccp(offsetPix.x,offsetPix.y), ccp(offsetPix.x+s.width,offsetPix.y),
		ccp(offsetPix.x+s.width,offsetPix.y+s.height), ccp(offsetPix.x,offsetPix.y+s.height)
	};
	ccDrawPoly(vertices, 4, true);
#endif // CC_SPRITE_DEBUG_DRAW

	CC_INCREMENT_GL_DRAWS(1);

	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "CCSquirmAnimNode - draw");
}
void CCParticleSystemFrameQuad::update(float dt)
{
    CC_PROFILER_START_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystemFrameQuad - update");

    if (m_bIsActive && m_fEmissionRate)
    {
        float rate = 1.0f / m_fEmissionRate;
        //issue #1201, prevent bursts of particles, due to too high emitCounter
        if (m_uParticleCount < m_uTotalParticles)
        {
            m_fEmitCounter += dt;
        }
        
        while (m_uParticleCount < m_uTotalParticles && m_fEmitCounter > rate) 
        {
            this->addParticle();
            m_fEmitCounter -= rate;
        }

        m_fElapsed += dt;
        if (m_fDuration != -1 && m_fDuration < m_fElapsed)
        {
            this->stopSystem();
        }
    }

    m_uParticleIdx = 0;

    CCPoint currentPosition = CCPointZero;
    if (m_ePositionType == kCCPositionTypeFree)
    {
        currentPosition = this->convertToWorldSpace(CCPointZero);
    }
    else if (m_ePositionType == kCCPositionTypeRelative)
    {
        currentPosition = m_obPosition;
    }

    if (m_bVisible)
    {
        while (m_uParticleIdx < m_uParticleCount)
        {
            tCCParticle *p = &m_pParticles[m_uParticleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0) 
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (m_nEmitterMode == kCCParticleModeGravity) 
                {
                    CCPoint tmp, radial, tangential;

                    radial = CCPointZero;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = ccpNormalize(p->pos);
                    }
                    tangential = radial;
                    radial = ccpMult(radial, p->modeA.radialAccel);

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = ccpMult(tangential, p->modeA.tangentialAccel);

                    // (gravity + radial + tangential) * dt
                    tmp = ccpAdd( ccpAdd( radial, tangential), modeA.gravity);
                    tmp = ccpMult( tmp, dt);
                    p->modeA.dir = ccpAdd( p->modeA.dir, tmp);
                    tmp = ccpMult(p->modeA.dir, dt);
                    p->pos = ccpAdd( p->pos, tmp );
                }

                // Mode B: radius movement
                else 
                {                
                    // Update the angle and radius of the particle.
                    p->modeB.angle += p->modeB.degreesPerSecond * dt;
                    p->modeB.radius += p->modeB.deltaRadius * dt;

                    p->pos.x = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius;
                }

                // color
                p->color.r += (p->deltaColor.r * dt);
                p->color.g += (p->deltaColor.g * dt);
                p->color.b += (p->deltaColor.b * dt);
                p->color.a += (p->deltaColor.a * dt);

                // size
                p->size += (p->deltaSize * dt);
                p->size = MAX( 0, p->size );

                // angle
                p->rotation += (p->deltaRotation * dt);

                //
                // update values in quad
                //

                CCPoint    newPos;

                if (m_ePositionType == kCCPositionTypeFree || m_ePositionType == kCCPositionTypeRelative) 
                {
                    CCPoint diff = ccpSub( currentPosition, p->startPos );
                    newPos = ccpSub(p->pos, diff);
                } 
                else
                {
                    newPos = p->pos;
                }

                // translate newPos to correct position, since matrix transform isn't performed in batchnode
                // don't update the particle with the new position information, it will interfere with the radius and tangential calculations
                if (m_pBatchNode)
                {
                    newPos.x+=m_obPosition.x;
                    newPos.y+=m_obPosition.y;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++m_uParticleIdx;
            } 
            else 
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( m_uParticleIdx != m_uParticleCount-1 )
                {
                    m_pParticles[m_uParticleIdx] = m_pParticles[m_uParticleCount-1];
                }
                if (m_pBatchNode)
                {
                    //disable the switched particle
                    m_pBatchNode->disableParticle(m_uAtlasIndex+currentIndex);

                    //switch indexes
                    m_pParticles[m_uParticleCount-1].atlasIndex = currentIndex;
                }
				else if( m_uParticleIdx != m_uParticleCount-1 )
				{
					//switch quads texCoords
					ccV3F_C4B_T2F_Quad temp = m_pQuads[m_uParticleIdx];
					m_pQuads[m_uParticleIdx] = m_pQuads[m_uParticleCount-1];
					m_pQuads[m_uParticleCount-1] = temp;
				}


                --m_uParticleCount;

                if( m_uParticleCount == 0 && m_bIsAutoRemoveOnFinish )
                {
                    this->unscheduleUpdate();
                    m_pParent->removeChild(this, true);
                    return;
                }
            }
        } //while
        m_bTransformSystemDirty = false;
    }
    if (! m_pBatchNode)
    {
        postStep();
    }

    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , "CCParticleSystemFrameQuad - update");
}
void GAFSprite::draw(void)
{
	if (_isLocator)
	{
		return;
	}
    CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "GAFSprite - draw");
	
    CCAssert(!m_pobBatchNode, "If CCSprite is being rendered by CCSpriteBatchNode, CCSprite#draw SHOULD NOT be called");
	
    CC_NODE_DRAW_SETUP();
	
    if (_useSeparateBlendFunc)
    {
        glBlendFuncSeparate(_blendFuncSeparate.src,      _blendFuncSeparate.dst,
                            _blendFuncSeparate.srcAlpha, _blendFuncSeparate.dstAlpha);
    }
    else
    {
        ccGLBlendFunc(m_sBlendFunc.src, m_sBlendFunc.dst);
    }
    
    if (_blendEquation != -1)
    {
        glBlendEquation(_blendEquation);
    }
	
    if (m_pobTexture != NULL)
    {
        ccGLBindTexture2D( m_pobTexture->getName() );
    }
    else
    {
        ccGLBindTexture2D(0);
    }
    
    //
    // Attributes
    //
	
    ccGLEnableVertexAttribs( kCCVertexAttribFlag_PosColorTex );
	setUniformsForFragmentShader();
	CHECK_GL_ERROR_DEBUG();
	
#define kQuadSize sizeof(m_sQuad.bl)
    long offset = (long)&m_sQuad;
	
    // vertex
    int diff = offsetof( ccV3F_C4B_T2F, vertices);
    glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
	
    // texCoods
    diff = offsetof( ccV3F_C4B_T2F, texCoords);
    glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
	
    // color
    diff = offsetof( ccV3F_C4B_T2F, colors);
    glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
	
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
	
    CHECK_GL_ERROR_DEBUG();	
	
    CC_INCREMENT_GL_DRAWS(1);
	
    CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "GAFSprite - draw");
}
void BillboardParticleSystem::update(float dt)
{
    if(_camera)
    {
        const Mat4& cameraViewMatrix = _camera->getViewMatrix().getInversed();
        cameraViewMatrix.getRightVector(&_cameraRight);
        cameraViewMatrix.getUpVector(&_cameraUp);
    }
    const Mat4& WorldMat = getNodeToWorldTransform();
    Quaternion rotation;;
    WorldMat.getRotation(&rotation);
    Mat4 roaMat;
    Mat4::createRotation(rotation,&roaMat);

    CC_PROFILER_START_CATEGORY(kProfilerCategoryParticles , "CCParticleSystem - update");
    if (_isActive && _emissionRate)
    {
        float rate = 1.0f / _emissionRate;
        //issue #1201, prevent bursts of particles, due to too high emitCounter
        if (_particleCount < _totalParticles)
        {
            _emitCounter += dt;
        }

        while (_particleCount < _totalParticles && _emitCounter > rate) 
        {
            this->addParticle();
            _emitCounter -= rate;
        }

        _elapsed += dt;
        if (_duration != -1 && _duration < _elapsed)
        {
            this->stopSystem();
        }
    }

    _particleIdx = 0;

    Vec3 currentPosition = Vec3::ZERO;
    if (_positionType == PositionType::FREE)
    {
        currentPosition = this->convertToWorldSpace3D(Vec3::ZERO);
    }
    else if (_positionType == PositionType::RELATIVE)
    {
        currentPosition.x = _position.x;
        currentPosition.y = _position.y;
        currentPosition.z = _positionZ;
    }

    {
        while (_particleIdx < _particleCount)
        {
            sBillboardParticle *p = &_particles[_particleIdx];

            // life
            p->timeToLive -= dt;

            if (p->timeToLive > 0) 
            {
                // Mode A: gravity, direction, tangential accel & radial accel
                if (_emitterMode == Mode::GRAVITY)
                {
                    Vec2 tmp, radial, tangential;

                    radial = Vec2::ZERO;
                    // radial acceleration
                    if (p->pos.x || p->pos.y)
                    {
                        radial = p->pos.getNormalized();
                    }
                    tangential = radial;
                    radial = radial * p->modeA.radialAccel;

                    // tangential acceleration
                    float newy = tangential.x;
                    tangential.x = -tangential.y;
                    tangential.y = newy;
                    tangential = tangential * p->modeA.tangentialAccel;

                    // (gravity + radial + tangential) * dt
                    tmp = radial + tangential + modeA.gravity;
                    tmp = tmp * dt;
                    p->modeA.dir = p->modeA.dir + tmp;

                    // this is cocos2d-x v3.0
                    //                    if (_configName.length()>0 && _yCoordFlipped != -1)

                    // this is cocos2d-x v3.0
                    tmp = p->modeA.dir * dt * _yCoordFlipped;
                    p->pos = p->pos + tmp;
                }

                // Mode B: radius movement
                else 
                {                
                    // Update the angle and radius of the particle.
                    p->modeB.angle += p->modeB.degreesPerSecond * dt;
                    p->modeB.radius += p->modeB.deltaRadius * dt;

                    p->pos.x = - cosf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y = - sinf(p->modeB.angle) * p->modeB.radius;
                    p->pos.y *= _yCoordFlipped;
                }

                // color
                p->color.r += (p->deltaColor.r * dt);
                p->color.g += (p->deltaColor.g * dt);
                p->color.b += (p->deltaColor.b * dt);
                p->color.a += (p->deltaColor.a * dt);

                // size
                p->size += (p->deltaSize * dt);
                p->size = MAX( 0, p->size );

                // angle
                p->rotation += (p->deltaRotation * dt);

                //
                // update values in quad
                //

                Vec3    newPos;
                Vec3 parPos(p->pos.x,p->pos.y,0);
                roaMat.transformVector(&parPos);
                if (_positionType == PositionType::FREE)
                {
                    Vec3 diff = convertToNodeSpace3D(currentPosition) - convertToNodeSpace3D(p->startPos);
                    //newPos.x =  p->pos.x - diff.x;
                    //newPos.y =  p->pos.y - diff.y;
                    //newPos.z = - diff.z;
                    newPos = parPos-diff;
                }
                else if(_positionType == PositionType::RELATIVE)
                {
                    Vec3 diff = currentPosition - p->startPos;
                    newPos.x = p->pos.x - diff.x;
                    newPos.y =  p->pos.y - diff.y;
                    newPos.z = - diff.z;
                } 
                else
                {
                    newPos.x = p->pos.x;
                    newPos.y = p->pos.y;
                    newPos.z = 0;
                }

                updateQuadWithParticle(p, newPos);
                //updateParticleImp(self, updateParticleSel, p, newPos);

                // update particle counter
                ++_particleIdx;
            } 
            else 
            {
                // life < 0
                int currentIndex = p->atlasIndex;
                if( _particleIdx != _particleCount-1 )
                {
                    _particles[_particleIdx] = _particles[_particleCount-1];
                }
                --_particleCount;

                if( _particleCount == 0 && _isAutoRemoveOnFinish )
                {
                    this->unscheduleUpdate();
                    _parent->removeChild(this, true);
                    return;
                }
            }
        } //while
        _transformSystemDirty = false;
    }

    // only update gl buffer when visible
    if (_visible)
    {
        postStep();
    }

    CC_PROFILER_STOP_CATEGORY(kProfilerCategoryParticles , "BillboardParticleSystem - update");
}