123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- /****************************************************************************
- Copyright (c) 2015-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
-
- http://www.cocos2d-x.org
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include "extensions/Particle3D/CCParticleSystem3D.h"
- #include "extensions/Particle3D/CCParticle3DRender.h"
- #include "renderer/CCMeshCommand.h"
- #include "renderer/CCRenderer.h"
- #include "renderer/CCTextureCache.h"
- #include "renderer/CCGLProgramState.h"
- #include "renderer/CCGLProgramCache.h"
- #include "renderer/CCVertexIndexBuffer.h"
- #include "renderer/CCVertexAttribBinding.h"
- #include "base/CCDirector.h"
- #include "3d/CCSprite3D.h"
- #include "2d/CCCamera.h"
- NS_CC_BEGIN
- Particle3DQuadRender::Particle3DQuadRender()
- : _meshCommand(nullptr)
- , _texture(nullptr)
- , _glProgramState(nullptr)
- , _indexBuffer(nullptr)
- , _vertexBuffer(nullptr)
- , _texFile("")
- {
- }
- Particle3DQuadRender::~Particle3DQuadRender()
- {
- CC_SAFE_DELETE(_meshCommand);
- //CC_SAFE_RELEASE(_texture);
- CC_SAFE_RELEASE(_glProgramState);
- CC_SAFE_RELEASE(_vertexBuffer);
- CC_SAFE_RELEASE(_indexBuffer);
- }
- Particle3DQuadRender* Particle3DQuadRender::create(const std::string& texFile)
- {
- auto ret = new (std::nothrow)Particle3DQuadRender();
- if (ret && ret->initQuadRender(texFile))
- {
- ret->_texFile = texFile;
- ret->autorelease();
- }
- else
- {
- CC_SAFE_DELETE(ret);
- }
- return ret;
- }
- void Particle3DQuadRender::render(Renderer* renderer, const Mat4 &transform, ParticleSystem3D* particleSystem)
- {
- //batch and generate draw
- const ParticlePool &particlePool = particleSystem->getParticlePool();
- if (!_isVisible || particlePool.empty())
- return;
-
- if (_vertexBuffer == nullptr){
- GLsizei stride = sizeof(Particle3DQuadRender::posuvcolor);
- _vertexBuffer = VertexBuffer::create(stride, 4 * particleSystem->getParticleQuota());
- if (_vertexBuffer == nullptr)
- {
- CCLOG("Particle3DQuadRender::render create vertex buffer failed");
- return;
- }
- _vertexBuffer->retain();
- }
- if (_indexBuffer == nullptr){
- _indexBuffer = IndexBuffer::create(IndexBuffer::IndexType::INDEX_TYPE_SHORT_16, 6 * particleSystem->getParticleQuota());
- if (_indexBuffer == nullptr)
- {
- CCLOG("Particle3DQuadRender::render create index buffer failed");
- return;
- }
- _indexBuffer->retain();
- }
- ParticlePool::PoolList activeParticleList = particlePool.getActiveDataList();
- if (_posuvcolors.size() < activeParticleList.size() * 4)
- {
- _posuvcolors.resize(activeParticleList.size() * 4);
- _indexData.resize(activeParticleList.size() * 6);
- }
- auto camera = Camera::getVisitingCamera();
- auto cameraMat = camera->getNodeToWorldTransform();
- const Mat4 &viewMat = cameraMat.getInversed();
-
- Mat4 pRotMat;
- Vec3 right(cameraMat.m[0], cameraMat.m[1], cameraMat.m[2]);
- Vec3 up(cameraMat.m[4], cameraMat.m[5], cameraMat.m[6]);
- Vec3 backward(cameraMat.m[8], cameraMat.m[9], cameraMat.m[10]);
-
- Vec3 position; //particle position
- int vertexindex = 0;
- int index = 0;
- for (auto iter : activeParticleList)
- {
- auto particle = iter;
- Vec3 halfwidth = particle->width * 0.5f * right;
- Vec3 halfheight = particle->height * 0.5f * up;
- //transform.transformPoint(particle->position, &position);
- position = particle->position;
- _posuvcolors[vertexindex].position = (position + (- halfwidth - halfheight));
- _posuvcolors[vertexindex].color = particle->color;
- _posuvcolors[vertexindex].uv.set(particle->lb_uv);
- _posuvcolors[vertexindex + 1].position = (position + (halfwidth - halfheight));
- _posuvcolors[vertexindex + 1].color = particle->color;
- _posuvcolors[vertexindex + 1].uv.set(particle->rt_uv.x, particle->lb_uv.y);
-
- _posuvcolors[vertexindex + 2].position = (position + (- halfwidth + halfheight));
- _posuvcolors[vertexindex + 2].color = particle->color;
- _posuvcolors[vertexindex + 2].uv.set(particle->lb_uv.x, particle->rt_uv.y);
-
- _posuvcolors[vertexindex + 3].position = (position + (halfwidth + halfheight));
- _posuvcolors[vertexindex + 3].color = particle->color;
- _posuvcolors[vertexindex + 3].uv.set(particle->rt_uv);
-
-
- _indexData[index] = vertexindex;
- _indexData[index + 1] = vertexindex + 1;
- _indexData[index + 2] = vertexindex + 3;
- _indexData[index + 3] = vertexindex;
- _indexData[index + 4] = vertexindex + 3;
- _indexData[index + 5] = vertexindex + 2;
-
- index += 6;
- vertexindex += 4;
- }
-
- _posuvcolors.erase(_posuvcolors.begin() + vertexindex, _posuvcolors.end());
- _indexData.erase(_indexData.begin() + index, _indexData.end());
-
- _vertexBuffer->updateVertices(&_posuvcolors[0], vertexindex/* * sizeof(_posuvcolors[0])*/, 0);
- _indexBuffer->updateIndices(&_indexData[0], index/* * sizeof(unsigned short)*/, 0);
-
- GLuint texId = (_texture ? _texture->getName() : 0);
- float depthZ = -(viewMat.m[2] * transform.m[12] + viewMat.m[6] * transform.m[13] + viewMat.m[10] * transform.m[14] + viewMat.m[14]);
- _meshCommand->init(
- depthZ,
- texId,
- _glProgramState,
- _stateBlock,
- _vertexBuffer->getVBO(),
- _indexBuffer->getVBO(),
- GL_TRIANGLES,
- GL_UNSIGNED_SHORT,
- index,
- transform,
- 0);
- _glProgramState->setUniformVec4("u_color", Vec4(1,1,1,1));
- renderer->addCommand(_meshCommand);
- }
- bool Particle3DQuadRender::initQuadRender( const std::string& texFile )
- {
- GLProgram* glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_PARTICLE_COLOR);
- if (!texFile.empty())
- {
- auto tex = Director::getInstance()->getTextureCache()->addImage(texFile);
- if (tex)
- {
- _texture = tex;
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_PARTICLE_TEXTURE);
- }
- else
- _texture = nullptr;
- }
- auto glProgramState = GLProgramState::create(glProgram);
- glProgramState->retain();
- GLsizei stride = sizeof(Particle3DQuadRender::posuvcolor);
- glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_POSITION], 3, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(posuvcolor, position));
- glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_TEX_COORD], 2, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(posuvcolor, uv));
- glProgramState->setVertexAttribPointer(s_attributeNames[GLProgram::VERTEX_ATTRIB_COLOR], 4, GL_FLOAT, GL_FALSE, stride, (GLvoid*)offsetof(posuvcolor, color));
- _glProgramState = glProgramState;
- //ret->_vertexBuffer = VertexBuffer::create(stride, 4 * 10000);
- //ret->_vertexBuffer->retain();
- //ret->_indexBuffer = IndexBuffer::create(IndexBuffer::IndexType::INDEX_TYPE_SHORT_16, 6 * 10000);
- //ret->_indexBuffer->retain();
- _meshCommand = new (std::nothrow) MeshCommand();
- _meshCommand->setSkipBatching(true);
- _meshCommand->setTransparent(true);
- _stateBlock->setDepthTest(_depthTest);
- _stateBlock->setDepthWrite(_depthWrite);
- _stateBlock->setCullFace(true);
- _stateBlock->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
- return true;
- }
- void Particle3DQuadRender::reset()
- {
- this->initQuadRender(_texFile);
- }
- //////////////////////////////////////////////////////////////////////////////
- Particle3DModelRender::Particle3DModelRender()
- : _spriteSize(Vec3::ONE)
- {
-
- }
- Particle3DModelRender::~Particle3DModelRender()
- {
- for (auto iter : _spriteList){
- iter->release();
- }
- }
- Particle3DModelRender* Particle3DModelRender::create(const std::string& modelFile, const std::string &texFile)
- {
- auto ret = new (std::nothrow) Particle3DModelRender();
- ret->_modelFile = modelFile;
- ret->_texFile = texFile;
- return ret;
- }
- void Particle3DModelRender::render(Renderer* renderer, const Mat4 &transform, ParticleSystem3D* particleSystem)
- {
- if (!_isVisible)
- return;
-
- if (_spriteList.empty()){
- for (unsigned int i = 0; i < particleSystem->getParticleQuota(); ++i){
- Sprite3D *sprite = Sprite3D::create(_modelFile);
- if (sprite == nullptr)
- {
- CCLOG("failed to load file %s", _modelFile.c_str());
- continue;
- }
- sprite->setTexture(_texFile);
- sprite->retain();
- _spriteList.push_back(sprite);
- }
- if (!_spriteList.empty()){
- const AABB &aabb = _spriteList[0]->getAABB();
- Vec3 corners[8];
- aabb.getCorners(corners);
- _spriteSize = corners[3] - corners[6];
- }
- }
- const ParticlePool& particlePool = particleSystem->getParticlePool();
- ParticlePool::PoolList activeParticleList = particlePool.getActiveDataList();
- Mat4 mat;
- Mat4 rotMat;
- Mat4 sclMat;
- Quaternion q;
- transform.decompose(nullptr, &q, nullptr);
- unsigned int index = 0;
- for (auto iter : activeParticleList)
- {
- auto particle = iter;
- Mat4::createRotation(q * particle->orientation, &rotMat);
- sclMat.m[0] = particle->width / _spriteSize.x;
- sclMat.m[5] = particle->height / _spriteSize.y;
- sclMat.m[10] = particle->depth / _spriteSize.z;
- mat = rotMat * sclMat;
- mat.m[12] = particle->position.x;
- mat.m[13] = particle->position.y;
- mat.m[14] = particle->position.z;
- _spriteList[index++]->draw(renderer, mat, 0);
- }
- }
- void Particle3DModelRender::reset()
- {
- for (auto iter : _spriteList){
- iter->release();
- }
- _spriteList.clear();
- }
- // MARK: Particle3DRender
- Particle3DRender::Particle3DRender()
- : _particleSystem(nullptr)
- , _isVisible(true)
- , _rendererScale(Vec3::ONE)
- , _depthTest(true)
- , _depthWrite(false)
- {
- _stateBlock = RenderState::StateBlock::create();
- _stateBlock->retain();
- _stateBlock->setCullFace(false);
- _stateBlock->setCullFaceSide(RenderState::CULL_FACE_SIDE_BACK);
- _stateBlock->setDepthTest(false);
- _stateBlock->setDepthWrite(false);
- _stateBlock->setBlend(true);
- };
- Particle3DRender::~Particle3DRender()
- {
- _stateBlock->release();
- }
- void Particle3DRender::copyAttributesTo (Particle3DRender *render)
- {
- CC_SAFE_RELEASE(render->_stateBlock);
- render->_stateBlock = _stateBlock;
- CC_SAFE_RETAIN(render->_stateBlock);
- render->_isVisible = _isVisible;
- render->_rendererScale = _rendererScale;
- render->_depthTest = _depthTest;
- render->_depthWrite = _depthWrite;
- }
- void Particle3DRender::notifyStart()
- {
- setVisible(true);
- }
- void Particle3DRender::notifyStop()
- {
- setVisible(false);
- }
- void Particle3DRender::notifyRescaled( const Vec3& scale )
- {
- _rendererScale = scale;
- }
- void Particle3DRender::setDepthTest( bool isDepthTest )
- {
- _depthTest = isDepthTest;
- _stateBlock->setDepthTest(_depthTest);
- }
- void Particle3DRender::setDepthWrite( bool isDepthWrite )
- {
- _depthWrite = isDepthWrite;
- _stateBlock->setDepthWrite(_depthWrite);
- }
- void Particle3DRender::setBlendFunc(const BlendFunc &blendFunc)
- {
- _stateBlock->setBlendFunc(blendFunc);
- }
- NS_CC_END
|