初始化

This commit is contained in:
SmallMain
2022-06-25 00:23:03 +08:00
commit ef0589e8e5
2264 changed files with 617829 additions and 0 deletions

View File

@@ -0,0 +1,179 @@
/****************************************************************************
Copyright (c) 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 "MemPool.hpp"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "base/ccMacros.h"
RENDERER_BEGIN
UnitBase::UnitBase()
{
}
UnitBase::~UnitBase()
{
}
void UnitBase::set(se::Object** dataObj, uint8_t** data, std::size_t* dataLen, se::Object* jsData)
{
if (*dataObj == jsData) return;
if (*dataObj)
{
(*dataObj)->unroot();
(*dataObj)->decRef();
*dataObj = nullptr;
}
if (jsData == nullptr) return;
*dataObj = jsData;
(*dataObj)->root();
(*dataObj)->incRef();
*data = nullptr;
*dataLen = 0;
(*dataObj)->getTypedArrayData(data, dataLen);
}
void UnitBase::unset(se::Object** dataObj, uint8_t** data, std::size_t* dataLen)
{
if (*dataObj)
{
(*dataObj)->unroot();
(*dataObj)->decRef();
*dataObj = nullptr;
}
*data = nullptr;
*dataLen = 0;
}
UnitCommon::UnitCommon()
{
}
UnitCommon::~UnitCommon()
{
unset(&dataObj, (uint8_t**)&data, &dataLen);
unset(&signDataObj, (uint8_t**)&signData, &signDataLen);
}
void UnitCommon::setData(se::Object* jsData)
{
set(&dataObj, (uint8_t**)&data, &dataLen, jsData);
}
void UnitCommon::setSignData(se::Object* jsSignData)
{
set(&signDataObj, (uint8_t**)&signData, &signDataLen, jsSignData);
}
MemPool::MemPool()
{
}
MemPool::~MemPool()
{
for(auto it = _commonPool.begin(); it != _commonPool.end(); it++)
{
if (*it)
{
delete (*it);
}
}
_commonPool.clear();
}
void MemPool::removeCommonData(std::size_t unitID)
{
CCASSERT(unitID < _commonPool.size(), "MemPool removeCommonData unitID can not be rather than pool size");
auto unit = _commonPool[unitID];
if (unit)
{
for (auto it = _commonList.begin(); it != _commonList.end(); it++)
{
if ((*it)->unitID == unitID)
{
_commonList.erase(it);
break;
}
}
delete unit;
_commonPool[unitID] = nullptr;
}
}
void MemPool::updateCommonData(std::size_t unitID, se_object_ptr dataObj, se_object_ptr signDataObj)
{
CCASSERT(unitID <= _commonPool.size(), "MemPool updateData unitID can not be rather than pool size");
UnitCommon* unit = nullptr;
if (unitID == _commonPool.size())
{
unit = new UnitCommon;
_commonPool.push_back(unit);
_commonList.push_back(unit);
}
else if (unitID < _commonPool.size())
{
unit = _commonPool[unitID];
if (!unit)
{
unit = new UnitCommon;
_commonPool[unitID] = unit;
_commonList.push_back(unit);
}
}
else
{
return;
}
unit->unitID = unitID;
unit->setData(dataObj);
unit->setSignData(signDataObj);
}
const std::vector<UnitCommon*>& MemPool::getCommonPool() const
{
return _commonPool;
}
const std::vector<UnitCommon*>& MemPool::getCommonList() const
{
return _commonList;
}
UnitCommon* MemPool::getCommonUnit(std::size_t unitID)
{
CCASSERT(unitID < _commonPool.size(), "MemPool getCommonUnit unitID can not be rather than pool size");
return _commonPool[unitID];
}
RENDERER_END

View File

@@ -0,0 +1,99 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../Macro.h"
#include <vector>
#include "scripting/js-bindings/jswrapper/Object.hpp"
RENDERER_BEGIN
class UnitBase
{
public:
UnitBase();
virtual ~UnitBase();
void set(se::Object** dataObj, uint8_t** data, std::size_t* dataLen, se::Object* jsData);
void unset(se::Object** dataObj, uint8_t** data, std::size_t* dataLen);
std::size_t unitID = 0;
};
struct Sign
{
uint16_t nextFreeIndex;
uint16_t freeFlag;
};
class UnitCommon: public UnitBase
{
public:
UnitCommon();
virtual ~UnitCommon();
void setData(se::Object* jsData);
void setSignData(se::Object* jsSignData);
uint16_t getUsingNum()
{
return data[1];
}
Sign* getSignData(std::size_t index)
{
return (Sign*)signData + index;
}
std::size_t getContentNum()
{
return signDataLen / (sizeof(uint16_t) * 2);
}
protected:
se::Object* dataObj = nullptr;
uint16_t* data = nullptr;
std::size_t dataLen = 0;
se::Object* signDataObj = nullptr;
uint16_t* signData = nullptr;
std::size_t signDataLen = 0;
};
class MemPool {
public:
MemPool();
virtual ~MemPool();
void removeCommonData(std::size_t unitID);
void updateCommonData(std::size_t unitID, se_object_ptr dataObj, se_object_ptr signDataObj);
UnitCommon* getCommonUnit(std::size_t unitID);
const std::vector<UnitCommon*>& getCommonPool() const;
const std::vector<UnitCommon*>& getCommonList() const;
private:
std::vector<UnitCommon*> _commonPool;
std::vector<UnitCommon*> _commonList;
};
RENDERER_END

View File

@@ -0,0 +1,227 @@
/****************************************************************************
Copyright (c) 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 "MeshBuffer.hpp"
#include "../Types.h"
#include "ModelBatcher.hpp"
#include "RenderFlow.hpp"
#include "../gfx/DeviceGraphics.h"
#define MAX_VERTEX_COUNT 65535
RENDERER_BEGIN
MeshBuffer::MeshBuffer(ModelBatcher* batcher, VertexFormat* fmt)
: _vertexFmt(fmt)
, _batcher(batcher)
{
_bytesPerVertex = _vertexFmt->getBytes();
DeviceGraphics* device = _batcher->getFlow()->getDevice();
_vb = VertexBuffer::create(device, _vertexFmt, Usage::DYNAMIC, nullptr, 0, 0);
_vbArr.pushBack(_vb);
_ib = IndexBuffer::create(device, IndexFormat::UINT16, Usage::STATIC, nullptr, 0, 0);
_ibArr.pushBack(_ib);
_vDataCount = MeshBuffer::INIT_VERTEX_COUNT * 4 * _bytesPerVertex / sizeof(float);
_iDataCount = MeshBuffer::INIT_VERTEX_COUNT * 6;
reallocVBuffer();
reallocIBuffer();
}
MeshBuffer::~MeshBuffer()
{
for (std::size_t i = 0, n = _vbArr.size(); i < n; i++)
{
_vbArr.at(i)->destroy();
}
_vbArr.clear();
for (std::size_t i = 0, n = _ibArr.size(); i < n; i++)
{
_ibArr.at(i)->destroy();
}
_ibArr.clear();
if (iData)
{
delete[] iData;
iData = nullptr;
}
if (vData)
{
delete[] vData;
vData = nullptr;
}
}
void MeshBuffer::reallocVBuffer()
{
auto oldVData = vData;
vData = new float[_vDataCount];
if (oldVData)
{
memcpy(vData, oldVData, sizeof(float) * _oldVDataCount);
delete[] oldVData;
oldVData = nullptr;
}
}
void MeshBuffer::reallocIBuffer()
{
auto oldIData = iData;
iData = new uint16_t[_iDataCount];
if (oldIData)
{
memcpy(iData, oldIData, sizeof(uint16_t) * _oldIDataCount);
delete[] oldIData;
oldIData = nullptr;
}
}
const MeshBuffer::OffsetInfo& MeshBuffer::request(uint32_t vertexCount, uint32_t indexCount)
{
if (_batcher->getCurrentBuffer() != this)
{
_batcher->flush();
_batcher->setCurrentBuffer(this);
}
_offsetInfo.vByte = _byteOffset;
_offsetInfo.index = _indexOffset;
_offsetInfo.vertex = _vertexOffset;
return requestStatic(vertexCount, indexCount);
}
const MeshBuffer::OffsetInfo& MeshBuffer::requestStatic(uint32_t vertexCount, uint32_t indexCount)
{
checkAndSwitchBuffer(vertexCount);
uint32_t byteOffset = _byteOffset + vertexCount * _bytesPerVertex;
uint32_t indexOffset = _indexOffset + indexCount;
uint32_t vBytes = _vDataCount * VDATA_BYTE;
if (byteOffset > vBytes)
{
_oldVDataCount = _vDataCount;
while (vBytes < byteOffset)
{
_vDataCount *= 2;
vBytes = _vDataCount * VDATA_BYTE;
}
reallocVBuffer();
}
if (indexOffset > _iDataCount)
{
_oldIDataCount = _iDataCount;
while (_iDataCount < indexOffset)
{
_iDataCount *= 2;
}
reallocIBuffer();
}
updateOffset(vertexCount, indexCount, byteOffset);
return _offsetInfo;
}
void MeshBuffer::uploadData()
{
_vb->update(0, vData, _byteOffset);
_ib->update(0, iData, _indexOffset * IDATA_BYTE);
_dirty = false;
}
void MeshBuffer::switchBuffer(uint32_t vertexCount)
{
std::size_t offset = ++_vbPos;
_byteOffset = 0;
_vertexOffset = 0;
_indexOffset = 0;
_indexStart = 0;
if (offset < _vbArr.size())
{
_vb = _vbArr.at(offset);
_ib = _ibArr.at(offset);
}
else
{
DeviceGraphics* device = _batcher->getFlow()->getDevice();
_vb = VertexBuffer::create(device, _vertexFmt, Usage::DYNAMIC, nullptr, 0, 0);
_vbArr.pushBack(_vb);
_ib = IndexBuffer::create(device, IndexFormat::UINT16, Usage::STATIC, nullptr, 0, 0);
_ibArr.pushBack(_ib);
}
}
void MeshBuffer::checkAndSwitchBuffer(uint32_t vertexCount)
{
if (_vertexOffset + vertexCount > MAX_VERTEX_COUNT)
{
uploadData();
_batcher->flush();
switchBuffer(vertexCount);
}
}
void MeshBuffer::updateOffset (uint32_t vertexCount, uint32_t indiceCount, uint32_t byteOffset)
{
_offsetInfo.vertex = _vertexOffset;
_vertexOffset += vertexCount;
_offsetInfo.index = _indexOffset;
_indexOffset += indiceCount;
_offsetInfo.vByte = _byteOffset;
_byteOffset = byteOffset;
_dirty = true;
}
void MeshBuffer::reset()
{
_vbPos = 0;
_vb = _vbArr.at(0);
_ib = _ibArr.at(0);
_byteStart = 0;
_byteOffset = 0;
_vertexStart = 0;
_vertexOffset = 0;
_indexStart = 0;
_indexOffset = 0;
_dirty = false;
}
RENDERER_END

View File

@@ -0,0 +1,189 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <stdint.h>
#include "../Macro.h"
#include "../gfx/VertexFormat.h"
#include "../gfx/VertexBuffer.h"
#include "../gfx/IndexBuffer.h"
#include "base/CCVector.h"
RENDERER_BEGIN
class ModelBatcher;
/**
* @addtogroup scene
* @{
*/
/**
* @brief The buffer which stores mesh render datas, including the vertices data and the indices data.
* It can be used as a global buffer shared by multiple render handles and eventually shared by Models
*/
class MeshBuffer
{
public:
/**
* @brief It describes a range of buffer in the global buffer, it contains result when you request the buffer.
*/
struct OffsetInfo
{
/** bytes count of the requested buffer */
uint32_t vByte = 0;
/** offset in index buffer */
uint32_t index = 0;
/** offset in vertex buffer */
uint32_t vertex = 0;
};
/**
* @brief Constructor
* @param[in] batcher The ModelBatcher which creates the current buffer
* @param[in] fmt The vertex format of vertex data
*/
MeshBuffer(ModelBatcher* batcher, VertexFormat* fmt);
/**
* @brief Destructor
*/
~MeshBuffer();
/**
* @brief Requests a range of buffer for the given count of vertices and indices
* @param[in] vertexCount Requested count of vertices
* @param[in] indexCount Requested count of indices
* @param[out] offset The result indicates the allocated buffer range
*/
const OffsetInfo& request(uint32_t vertexCount, uint32_t indexCount);
const OffsetInfo& requestStatic(uint32_t vertexCount, uint32_t indexCount);
/**
* @brief Upload data to GPU memory
*/
void uploadData();
/**
* @brief Reset all states.
*/
void reset();
/**
* @brief Gets the current byte offset which indicates the start of empty range
* @return Byte offset.
*/
uint32_t getByteOffset() const { return _byteOffset; };
/**
* @brief Gets the current vertex start offset since last time updateOffset is invoked
* @return Vertex start.
*/
uint32_t getVertexStart() const { return _vertexStart; };
/**
* @brief Gets the current vertex offset, which should equals to total allocated vertex count.
* @return Vertex offset.
*/
uint32_t getVertexOffset() const { return _vertexOffset; };
/**
* @brief Gets the current index start offset since last time updateOffset is invoked
* @return Index start.
*/
uint32_t getIndexStart() const { return _indexStart; };
/**
* @brief Gets the current index offset, which should equals to total allocated index count.
* @return Index offset.
*/
uint32_t getIndexOffset() const { return _indexOffset; };
/**
* @brief Update the current allocated offsets to the start offsets.
*/
void updateOffset()
{
_byteStart = _byteOffset;
_vertexStart = _vertexOffset;
_indexStart = _indexOffset;
};
/**
* @brief Gets the vertex buffer.
*/
VertexBuffer* getVertexBuffer() const { return _vb; };
/**
* @brief Gets the index buffer.
*/
IndexBuffer* getIndexBuffer() const { return _ib; };
/**
* @brief The vertex data storage in memory
*/
float* vData = nullptr;
/**
* @brief The index data storage in memory
*/
uint16_t* iData = nullptr;
/**
* @brief Vertex format of the vertex data.
*/
VertexFormat* _vertexFmt;
static const int INIT_VERTEX_COUNT = 4096;
static const uint8_t VDATA_BYTE = sizeof(float);
static const uint8_t IDATA_BYTE = sizeof(uint16_t);
protected:
void reallocVBuffer();
void reallocIBuffer();
void checkAndSwitchBuffer(uint32_t vertexCount);
void switchBuffer(uint32_t vertexCount);
void updateOffset(uint32_t vertexCount, uint32_t indiceCount, uint32_t byteOffset);
private:
uint32_t _byteStart = 0;
uint32_t _byteOffset = 0;
uint32_t _indexStart = 0;
uint32_t _indexOffset = 0;
uint32_t _vertexStart = 0;
uint32_t _vertexOffset = 0;
uint32_t _bytesPerVertex = 0;
uint32_t _vDataCount = 0;
uint32_t _iDataCount = 0;
uint32_t _oldVDataCount = 0;
uint32_t _oldIDataCount = 0;
bool _dirty = false;
ModelBatcher* _batcher = nullptr;
std::size_t _vbPos = 0;
cocos2d::Vector<VertexBuffer*> _vbArr;
cocos2d::Vector<IndexBuffer*> _ibArr;
VertexBuffer* _vb = nullptr;
IndexBuffer* _ib = nullptr;
OffsetInfo _offsetInfo;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,380 @@
/****************************************************************************
Copyright (c) 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 "ModelBatcher.hpp"
#include "RenderFlow.hpp"
#include "StencilManager.hpp"
#include "assembler/RenderDataList.hpp"
#include "NodeProxy.hpp"
RENDERER_BEGIN
#define INIT_MODEL_LENGTH 16
ModelBatcher::ModelBatcher(RenderFlow* flow)
: _flow(flow)
, _modelOffset(0)
, _cullingMask(0)
, _walking(false)
, _currEffect(nullptr)
, _buffer(nullptr)
, _useModel(false)
, _node(nullptr)
{
for (int i = 0; i < INIT_MODEL_LENGTH; i++)
{
_modelPool.push_back(new Model());
}
_stencilMgr = StencilManager::getInstance();
}
ModelBatcher::~ModelBatcher()
{
setCurrentEffect(nullptr);
setNode(nullptr);
for (int i = 0; i < _modelPool.size(); i++)
{
auto model = _modelPool[i];
delete model;
}
_modelPool.clear();
for (auto iter = _buffers.begin(); iter != _buffers.end(); ++iter)
{
MeshBuffer *buffer = iter->second;
delete buffer;
}
_buffers.clear();
}
void ModelBatcher::reset()
{
for (int i = 0; i < _modelOffset; ++i)
{
Model* model = _modelPool[i];
model->reset();
}
_flow->getRenderScene()->removeModels();
_modelOffset = 0;
for (auto iter : _buffers)
{
iter.second->reset();
}
_buffer = nullptr;
_commitState = CommitState::None;
setCurrentEffect(nullptr);
setNode(nullptr);
_ia.clear();
_cullingMask = 0;
_walking = false;
_useModel = false;
_modelMat.set(Mat4::IDENTITY);
_stencilMgr->reset();
}
void ModelBatcher::changeCommitState(CommitState state)
{
if (_commitState == state) return;
switch(_commitState)
{
case CommitState::Custom:
flushIA();
break;
case CommitState::Common:
flush();
break;
default:
break;
}
setCurrentEffect(nullptr);
_commitState = state;
}
void ModelBatcher::commit(NodeProxy* node, Assembler* assembler, int cullingMask)
{
changeCommitState(CommitState::Common);
bool useModel = assembler->getUseModel();
bool ignoreWorldMatrix = assembler->isIgnoreWorldMatrix();
auto customWorldMat = assembler->getCustomWorldMatrix();
customWorldMat = customWorldMat ? customWorldMat : &node->getWorldMatrix();
const Mat4& worldMat = useModel && !ignoreWorldMatrix ? *customWorldMat : Mat4::IDENTITY;
auto asmDirty = assembler->isDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
auto nodeDirty = node->isDirty(RenderFlow::NODE_OPACITY_CHANGED);
auto needUpdateOpacity = (asmDirty || nodeDirty) && !assembler->isIgnoreOpacityFlag();
for (std::size_t i = 0, l = assembler->getIACount(); i < l; ++i)
{
assembler->beforeFillBuffers(i);
EffectVariant* effect = assembler->getEffect(i);
if (!effect) continue;
if (_currEffect == nullptr ||
_currEffect->getHash() != effect->getHash() ||
_cullingMask != cullingMask || useModel)
{
// Break auto batch
flush();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
}
if (needUpdateOpacity)
{
assembler->updateOpacity(i, node->getRealOpacity());
}
assembler->fillBuffers(node, this, i);
}
}
void ModelBatcher::commitIA(NodeProxy* node, CustomAssembler* assembler, int cullingMask)
{
changeCommitState(CommitState::Custom);
EffectVariant* effect = assembler->getEffect(0);
if (!effect) return;
auto customIA = assembler->getIA(0);
if (!customIA) return;
std::size_t iaCount = assembler->getIACount();
bool useModel = assembler->getUseModel();
auto customWorldMat = assembler->getCustomWorldMatrix();
customWorldMat = customWorldMat ? customWorldMat : &node->getWorldMatrix();
const Mat4& worldMat = useModel ? *customWorldMat : Mat4::IDENTITY;
if (_currEffect == nullptr ||
_currEffect->getHash() != effect->getHash() ||
_cullingMask != cullingMask || useModel ||
!_ia.isMergeable(*customIA))
{
flushIA();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
_ia.setVertexBuffer(customIA->getVertexBuffer());
_ia.setIndexBuffer(customIA->getIndexBuffer());
_ia.setStart(customIA->getStart());
_ia.setCount(0);
}
for (std::size_t i = 0; i < iaCount; i++ )
{
customIA = assembler->getIA(i);
effect = assembler->getEffect(i);
if (!effect) continue;
if (i > 0)
{
flushIA();
setNode(_useModel ? node : nullptr);
setCurrentEffect(effect);
_modelMat.set(worldMat);
_useModel = useModel;
_cullingMask = cullingMask;
_ia.setVertexBuffer(customIA->getVertexBuffer());
_ia.setIndexBuffer(customIA->getIndexBuffer());
_ia.setStart(customIA->getStart());
_ia.setCount(0);
}
_ia.setCount(_ia.getCount() + customIA->getCount());
}
}
void ModelBatcher::flushIA()
{
if (_commitState != CommitState::Custom)
{
return;
}
if (!_walking || !_currEffect || _ia.getCount() <= 0)
{
_ia.clear();
return;
}
// Stencil manager process
_stencilMgr->handleEffect(_currEffect);
// Generate model
Model* model = nullptr;
if (_modelOffset >= _modelPool.size())
{
model = new Model();
_modelPool.push_back(model);
}
else
{
model = _modelPool[_modelOffset];
}
_modelOffset++;
model->setWorldMatix(_modelMat);
model->setCullingMask(_cullingMask);
model->setEffect(_currEffect);
model->setNode(_node);
model->setInputAssembler(_ia);
_ia.clear();
_flow->getRenderScene()->addModel(model);
}
void ModelBatcher::flush()
{
if (_commitState != CommitState::Common)
{
return;
}
if (!_walking || !_currEffect || !_buffer)
{
return;
}
int indexStart = _buffer->getIndexStart();
int indexOffset = _buffer->getIndexOffset();
int indexCount = indexOffset - indexStart;
if (indexCount <= 0)
{
return;
}
_ia.setVertexBuffer(_buffer->getVertexBuffer());
_ia.setIndexBuffer(_buffer->getIndexBuffer());
_ia.setStart(indexStart);
_ia.setCount(indexCount);
// Stencil manager process
_stencilMgr->handleEffect(_currEffect);
// Generate model
Model* model = nullptr;
if (_modelOffset >= _modelPool.size())
{
model = new Model();
_modelPool.push_back(model);
}
else
{
model = _modelPool[_modelOffset];
}
_modelOffset++;
model->setWorldMatix(_modelMat);
model->setCullingMask(_cullingMask);
model->setEffect(_currEffect);
model->setNode(_node);
model->setInputAssembler(_ia);
_ia.clear();
_flow->getRenderScene()->addModel(model);
_buffer->updateOffset();
}
void ModelBatcher::startBatch()
{
reset();
_walking = true;
}
void ModelBatcher::terminateBatch()
{
flush();
flushIA();
for (auto iter : _buffers)
{
iter.second->uploadData();
}
_walking = false;
}
void ModelBatcher::setNode(NodeProxy* node)
{
if (_node == node)
{
return;
}
CC_SAFE_RELEASE(_node);
_node = node;
CC_SAFE_RETAIN(_node);
}
void ModelBatcher::setCurrentEffect(EffectVariant* effect)
{
if (_currEffect == effect)
{
return;
}
CC_SAFE_RELEASE(_currEffect);
_currEffect = effect;
CC_SAFE_RETAIN(_currEffect);
};
MeshBuffer* ModelBatcher::getBuffer(VertexFormat* fmt)
{
if (_buffer != nullptr && fmt == _buffer->_vertexFmt)
{
return _buffer;
}
MeshBuffer* buffer = nullptr;
auto iter = _buffers.find(fmt);
if (iter == _buffers.end())
{
buffer = new MeshBuffer(this, fmt);
_buffers.emplace(fmt, buffer);
}
else
{
buffer = iter->second;
}
return buffer;
}
RENDERER_END

View File

@@ -0,0 +1,157 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <map>
#include "../Macro.h"
#include "assembler/Assembler.hpp"
#include "assembler/CustomAssembler.hpp"
#include "MeshBuffer.hpp"
#include "../renderer/Renderer.h"
#include "math/CCMath.h"
RENDERER_BEGIN
class RenderFlow;
class StencilManager;
/**
* @addtogroup scene
* @{
*/
/**
* @brief ModelBatcher is responsible for transforming node's render handles into final render datas.
* It collects render data, batches different render handle together into Models and submits to render Scene.
*/
class ModelBatcher
{
public:
enum CommitState {
None,
Common,
Custom,
};
/**
* @brief The constructor.
*/
ModelBatcher(RenderFlow* flow);
/**
* @brief The destructor.
*/
~ModelBatcher();
/**
* @brief Reset all render buffer.
*/
void reset();
/**
* @brief Commit a render handle to the model batcher
* @param[in] node The node which owns the render handle
* @param[in] handle The render handle contains render datas
*/
void commit(NodeProxy* node, Assembler* handle, int cullingMask);
/**
* @brief Commit a custom render handle to the model batcher
* @param[in] node The node which owns the render handle
* @param[in] handle The custom render handle contains render datas
*/
void commitIA(NodeProxy* node, CustomAssembler* handle, int cullingMask);
/**
* @brief This method should be invoked before commit any render handles each frame.
* It notifies the model batcher to get ready for constructing Models
*/
void startBatch();
/**
* @brief Flush all cached render data into a new Model and add the Model to render Scene.
*/
void flush();
/**
* @brief Finished Custom input assmebler batch and add the Model to render Scene.
*/
void flushIA();
/**
* @brief Add new input assembler into current input assembler.
*/
void flushIA(InputAssembler* customIA);
/**
* @brief This method should be invoked after committed all render handles each frame.
*/
void terminateBatch();
/**
* @brief Gets a suitable MeshBuffer for the given VertexFormat.
* Render datas arranged in different VertexFormat can't share the same buffer.
* @param[in] fmt The VertexFormat
*/
MeshBuffer* getBuffer(VertexFormat* fmt);
/**
* @brief Gets the current MeshBuffer.
*/
const MeshBuffer* getCurrentBuffer() const { return _buffer; };
/**
* @brief Sets the current MeshBuffer.
* @param[in] buffer
*/
void setCurrentBuffer(MeshBuffer* buffer) { _buffer = buffer; };
/**
* @brief Gets the global RenderFlow pointer.
*/
RenderFlow* getFlow() const { return _flow; };
void setNode(NodeProxy* node);
void setCullingMask(int cullingMask) { _cullingMask = cullingMask; }
void setCurrentEffect(EffectVariant* effect);
void setUseModel(bool useModel) { _useModel = useModel; }
void changeCommitState(CommitState state);
private:
int _modelOffset = 0;
int _cullingMask = 0;
bool _useModel = false;
bool _walking = false;
cocos2d::Mat4 _modelMat;
CommitState _commitState = CommitState::None;
NodeProxy* _node = nullptr;
MeshBuffer* _buffer = nullptr;
EffectVariant* _currEffect = nullptr;
RenderFlow* _flow = nullptr;
StencilManager* _stencilMgr = nullptr;
InputAssembler _ia;
std::vector<Model*> _modelPool;
std::unordered_map<VertexFormat*, MeshBuffer*> _buffers;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,186 @@
/****************************************************************************
Copyright (c) 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 "NodeMemPool.hpp"
#include "base/ccMacros.h"
RENDERER_BEGIN
UnitNode::UnitNode()
{
}
UnitNode::~UnitNode()
{
unset(&dirty, (uint8_t**)&dirtyData, &dirtyLen);
unset(&trs, (uint8_t**)&trsData, &trsLen);
unset(&localMat, (uint8_t**)&localMatData, &localMatLen);
unset(&worldMat, (uint8_t**)&worldMatData, &worldMatLen);
unset(&parent, (uint8_t**)&parentData, &parentLen);
unset(&zOrder, (uint8_t**)&zOrderData, &zOrderLen);
unset(&cullingMask, (uint8_t**)&cullingMaskData, &cullingMaskLen);
unset(&opacity, (uint8_t**)&opacityData, &opacityLen);
unset(&is3D, (uint8_t**)&is3DData, &is3DLen);
unset(&node, (uint8_t**)&nodeData, &nodeLen);
unset(&skew, (uint8_t**)&skewData, &skewLen);
}
void UnitNode::setDirty(se::Object* jsData)
{
set(&dirty, (uint8_t**)&dirtyData, &dirtyLen, jsData);
}
void UnitNode::setTRS(se::Object* jsData)
{
set(&trs, (uint8_t**)&trsData, &trsLen, jsData);
}
void UnitNode::setLocalMat(se::Object* jsData)
{
set(&localMat, (uint8_t**)&localMatData, &localMatLen, jsData);
}
void UnitNode::setWorldMat(se::Object* jsData)
{
set(&worldMat, (uint8_t**)&worldMatData, &worldMatLen, jsData);
}
void UnitNode::setParent(se::Object* jsData)
{
set(&parent, (uint8_t**)&parentData, &parentLen, jsData);
}
void UnitNode::setZOrder(se::Object* jsData)
{
set(&zOrder, (uint8_t**)&zOrderData, &zOrderLen, jsData);
}
void UnitNode::setCullingMask(se::Object* jsData)
{
set(&cullingMask, (uint8_t**)&cullingMaskData, &cullingMaskLen, jsData);
}
void UnitNode::setOpacity(se::Object* jsData)
{
set(&opacity, (uint8_t**)&opacityData, &opacityLen, jsData);
}
void UnitNode::setIs3D(se::Object* jsData)
{
set(&is3D, (uint8_t**)&is3DData, &is3DLen, jsData);
}
void UnitNode::setNode(se::Object *jsData)
{
set(&node, (uint8_t**)&nodeData, &nodeLen, jsData);
}
void UnitNode::setSkew(se::Object* jsData)
{
set(&skew, (uint8_t**)&skewData, &skewLen, jsData);
}
NodeMemPool* NodeMemPool::_instance = nullptr;
NodeMemPool::NodeMemPool()
{
_instance = this;
}
NodeMemPool::~NodeMemPool()
{
for(auto it = _nodePool.begin(); it != _nodePool.end(); it++)
{
if (*it)
{
delete (*it);
}
}
_nodePool.clear();
_instance = nullptr;
}
const std::vector<UnitNode*>& NodeMemPool::getNodePool() const
{
return _nodePool;
}
void NodeMemPool::removeNodeData(std::size_t unitID)
{
CCASSERT(unitID < _nodePool.size(), "NodeMemPool removeNodeData unitID can not be rather than pool size");
auto unit = _nodePool[unitID];
if (unit)
{
delete unit;
_nodePool[unitID] = nullptr;
}
}
UnitNode* NodeMemPool::getUnit(std::size_t unitID) const
{
CCASSERT(unitID < _nodePool.size(), "NodeMemPool getUnit unitID can not be rather than pool size");
return _nodePool[unitID];
}
void NodeMemPool::updateNodeData(std::size_t unitID, se_object_ptr dirty, se_object_ptr trs, se_object_ptr localMat, se_object_ptr worldMat, se_object_ptr parent, se_object_ptr zOrder, se_object_ptr cullingMask, se_object_ptr opacity, se_object_ptr is3D, se_object_ptr node, se_object_ptr skew)
{
// UnitID may equal to node pool size, then node pool must increase size.
CCASSERT(unitID <= _nodePool.size(), "NodeMemPool updateNodeData unitID can not be rather than pool size");
UnitNode* unit = nullptr;
if (unitID == _nodePool.size())
{
unit = new UnitNode;
_nodePool.push_back(unit);
}
else if (unitID < _nodePool.size())
{
unit = _nodePool[unitID];
if(!unit)
{
unit = new UnitNode;
_nodePool[unitID] = unit;
}
}
else
{
return;
}
unit->unitID = unitID;
unit->setDirty(dirty);
unit->setTRS(trs);
unit->setLocalMat(localMat);
unit->setWorldMat(worldMat);
unit->setParent(parent);
unit->setZOrder(zOrder);
unit->setCullingMask(cullingMask);
unit->setOpacity(opacity);
unit->setIs3D(is3D);
unit->setNode(node);
unit->setSkew(skew);
}
RENDERER_END

View File

@@ -0,0 +1,196 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "MemPool.hpp"
#include "math/Mat4.h"
RENDERER_BEGIN
class NodeProxy;
struct TRS {
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
float qx = 0.0f;
float qy = 0.0f;
float qz = 0.0f;
float qw = 0.0f;
float sx = 0.0f;
float sy = 0.0f;
float sz = 0.0f;
};
#define PARENT_INVALID 0xffffffff
struct ParentInfo {
uint32_t unitID = 0;
uint32_t index = 0;
};
struct Skew {
float_t x = 0.0f;
float_t y = 0.0f;
};
class UnitNode: public UnitBase {
public:
UnitNode();
virtual ~UnitNode();
void setDirty(se::Object* jsData);
void setTRS(se::Object* jsData);
void setLocalMat(se::Object* jsData);
void setWorldMat(se::Object* jsData);
void setParent(se::Object* jsData);
void setZOrder(se::Object* jsData);
void setCullingMask(se::Object* jsData);
void setOpacity(se::Object* jsData);
void setIs3D(se::Object* jsData);
void setNode(se::Object* jsData);
void setLevel(se::Object* jsData);
void setSkew(se::Object* jsData);
uint32_t* getDirty(std::size_t index) const
{
return dirtyData + index;
}
TRS* getTRS(std::size_t index) const
{
return (TRS*)trsData + index;
}
cocos2d::Mat4* getLocalMat(std::size_t index) const
{
return (cocos2d::Mat4*)localMatData + index;
}
cocos2d::Mat4* getWorldMat(std::size_t index) const
{
return (cocos2d::Mat4*)worldMatData + index;
}
ParentInfo* getParent(std::size_t index) const
{
return (ParentInfo*)parentData + index;
}
int32_t* getZOrder(std::size_t index) const
{
return zOrderData + index;
}
int32_t* getCullingMask(std::size_t index) const
{
return cullingMaskData + index;
}
uint8_t* getOpacity(std::size_t index) const
{
return opacityData + index;
}
uint8_t* getIs3D(std::size_t index) const
{
return is3DData + index;
}
uint64_t* getNode(std::size_t index) const
{
return nodeData + index;
}
Skew* getSkew(std::size_t index) const
{
return (Skew*)skewData + index;
}
protected:
se::Object* dirty = nullptr;
uint32_t* dirtyData = nullptr;
std::size_t dirtyLen = 0;
se::Object* trs = nullptr;
float_t* trsData = nullptr;
std::size_t trsLen = 0;
se::Object* localMat = nullptr;
float_t* localMatData = nullptr;
std::size_t localMatLen = 0;
se::Object* worldMat = nullptr;
float_t* worldMatData = nullptr;
std::size_t worldMatLen = 0;
se::Object* parent = nullptr;
uint32_t* parentData = nullptr;
std::size_t parentLen = 0;
se::Object* zOrder = nullptr;
int32_t* zOrderData = nullptr;
std::size_t zOrderLen = 0;
se::Object* cullingMask = nullptr;
int32_t* cullingMaskData = nullptr;
std::size_t cullingMaskLen = 0;
se::Object* opacity = nullptr;
uint8_t* opacityData = nullptr;
std::size_t opacityLen = 0;
se::Object* is3D = nullptr;
uint8_t* is3DData = nullptr;
std::size_t is3DLen = 0;
se::Object* node = nullptr;
uint64_t* nodeData = nullptr;
std::size_t nodeLen = 0;
se::Object* skew = nullptr;
float_t* skewData = nullptr;
std::size_t skewLen = 0;
};
class NodeMemPool: public MemPool {
public:
NodeMemPool();
virtual ~NodeMemPool();
static NodeMemPool* getInstance()
{
return _instance;
}
void removeNodeData(std::size_t unitID);
void updateNodeData(std::size_t unitID, se_object_ptr dirty, se_object_ptr trs, se_object_ptr localMat, se_object_ptr worldMat, se_object_ptr parent, se_object_ptr zOrder, se_object_ptr cullingMask, se_object_ptr opacity, se_object_ptr is3D, se_object_ptr node, se_object_ptr skew);
UnitNode* getUnit(std::size_t unitID) const;
const std::vector<UnitNode*>& getNodePool() const;
private:
static NodeMemPool* _instance;
std::vector<UnitNode*> _nodePool;
};
RENDERER_END

View File

@@ -0,0 +1,587 @@
/****************************************************************************
Copyright (c) 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 "NodeProxy.hpp"
#include <string>
#include "ModelBatcher.hpp"
#include "../renderer/Scene.h"
#include "base/ccMacros.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "cocos/scripting/js-bindings/manual/jsb_conversions.hpp"
#include "cocos/scripting/js-bindings/auto/jsb_renderer_auto.hpp"
#include "NodeMemPool.hpp"
#include <math.h>
#include "RenderFlow.hpp"
#include "assembler/AssemblerSprite.hpp"
RENDERER_BEGIN
uint32_t NodeProxy::_globalRenderOrder = 0;
NodeProxy::NodeProxy(std::size_t unitID, std::size_t index, const std::string& id, const std::string& name)
{
traverseHandle = render;
_id = id;
_unitID = unitID;
_index = index;
_name = name;
NodeMemPool* pool = NodeMemPool::getInstance();
CCASSERT(pool, "NodeProxy constructor NodeMemPool is null");
UnitNode* unit = pool->getUnit(unitID);
CCASSERT(unit, "NodeProxy constructor unit is null");
UnitCommon* common = pool->getCommonUnit(unitID);
_signData = common->getSignData(_index);
_dirty = unit->getDirty(index);
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
_trs = unit->getTRS(index);
_localMat = unit->getLocalMat(index);
_worldMat = unit->getWorldMat(index);
_parentInfo = unit->getParent(index);
_parentInfo->unitID = PARENT_INVALID;
_parentInfo->index = PARENT_INVALID;
_localZOrder = unit->getZOrder(index);
_cullingMask = unit->getCullingMask(index);
_opacity = unit->getOpacity(index);
_is3DNode = unit->getIs3D(index);
_skew = unit->getSkew(index);
uint64_t* self = unit->getNode(index);
*self = (uint64_t)this;
}
NodeProxy::~NodeProxy()
{
for (auto& child : _children)
{
child->_parent = nullptr;
}
CC_SAFE_RELEASE(_assembler);
}
void NodeProxy::destroyImmediately()
{
if (_parent)
{
_parent->removeChild(this);
}
RenderFlow::getInstance()->removeNodeLevel(_level, _worldMat);
CC_SAFE_RELEASE_NULL(_assembler);
_level = NODE_LEVEL_INVALID;
_dirty = nullptr;
_trs = nullptr;
_localMat = nullptr;
_worldMat = nullptr;
_parentInfo = nullptr;
_localZOrder = nullptr;
_cullingMask = nullptr;
_opacity = nullptr;
_is3DNode = nullptr;
_skew = nullptr;
}
// lazy allocs
void NodeProxy::childrenAlloc()
{
_children.reserve(4);
}
void NodeProxy::addChild(NodeProxy* child)
{
if (child == nullptr)
{
CCLOGWARN("Argument must be non-nil");
return;
}
if (child->_parent != nullptr)
{
CCLOGWARN("child already added. It can't be added again");
return;
}
auto assertNotSelfChild
( [ this, child ]() -> bool
{
for ( NodeProxy* parent( this ); parent != nullptr;
parent = parent->getParent() )
if ( parent == child )
return false;
return true;
} );
(void)assertNotSelfChild;
if (!assertNotSelfChild())
{
CCLOGWARN("A node cannot be the child of his own children" );
return;
}
if (_children.empty())
{
this->childrenAlloc();
}
_children.pushBack(child);
child->setParent(this);
}
void NodeProxy::detachChild(NodeProxy *child, ssize_t childIndex)
{
// set parent nil at the end
child->setParent(nullptr);
_children.erase(childIndex);
}
void NodeProxy::removeChild(NodeProxy* child)
{
// explicit nil handling
if (_children.empty())
{
return;
}
ssize_t index = _children.getIndex(child);
if( index != CC_INVALID_INDEX )
this->detachChild( child, index );
}
void NodeProxy::removeAllChildren()
{
// not using detachChild improves speed here
for (const auto& child : _children)
{
// set parent nil at the end
child->setParent(nullptr);
}
_children.clear();
}
NodeProxy* NodeProxy::getChildByName(std::string childName)
{
for (auto child : _children)
{
if (child->_name == childName)
{
return child;
}
}
return nullptr;
}
NodeProxy* NodeProxy::getChildByID(std::string id)
{
for (auto child : _children)
{
if (child->_id == id)
{
return child;
}
}
return nullptr;
}
void NodeProxy::notifyUpdateParent()
{
if (_parentInfo->index == PARENT_INVALID)
{
if (_parent)
{
_parent->removeChild(this);
}
updateLevel();
return;
}
NodeMemPool* pool = NodeMemPool::getInstance();
CCASSERT(pool, "NodeProxy updateParent NodeMemPool is null");
UnitNode* unit = pool->getUnit(_parentInfo->unitID);
CCASSERT(unit, "NodeProxy updateParent unit is null");
uint64_t* parentAddrs = unit->getNode(_parentInfo->index);
NodeProxy* parent = (NodeProxy*)*parentAddrs;
CCASSERT(parent, "NodeProxy updateParent parent is null");
if (parent != _parent) {
if (_parent)
{
_parent->removeChild(this);
}
parent->addChild(this);
updateLevel();
}
}
void NodeProxy::updateLevel()
{
static RenderFlow::LevelInfo levelInfo;
auto renderFlow = RenderFlow::getInstance();
renderFlow->removeNodeLevel(_level, _worldMat);
levelInfo.dirty = _dirty;
levelInfo.localMat = _localMat;
levelInfo.worldMat = _worldMat;
levelInfo.opacity = _opacity;
levelInfo.realOpacity = &_realOpacity;
if (_parent)
{
_level = _parent->_level + 1;
levelInfo.parentWorldMat = _parent->_worldMat;
levelInfo.parentDirty = _parent->_dirty;
levelInfo.parentRealOpacity = &_parent->_realOpacity;
}
else
{
_level = 0;
levelInfo.parentWorldMat = nullptr;
levelInfo.parentDirty = nullptr;
levelInfo.parentRealOpacity = nullptr;
}
renderFlow->insertNodeLevel(_level, levelInfo);
for (auto it = _children.begin(); it != _children.end(); it++)
{
(*it)->updateLevel();
}
}
void NodeProxy::setLocalZOrder(int zOrder)
{
if (*_localZOrder != zOrder)
{
*_localZOrder = zOrder;
if (_parent != nullptr)
{
*_parent->_dirty |= RenderFlow::REORDER_CHILDREN;
}
}
}
void NodeProxy::reorderChildren()
{
if (*_dirty & RenderFlow::REORDER_CHILDREN)
{
#if CC_64BITS
std::sort(std::begin(_children), std::end(_children), [](NodeProxy* n1, NodeProxy* n2) {
return (*n1->_localZOrder < *n2->_localZOrder);
});
#else
std::stable_sort(std::begin(_children), std::end(_children), [](NodeProxy* n1, NodeProxy* n2) {
return *n1->_localZOrder < *n2->_localZOrder;
});
#endif
*_dirty &= ~RenderFlow::REORDER_CHILDREN;
}
}
void NodeProxy::setAssembler(AssemblerBase* assembler)
{
if (assembler == _assembler) return;
CC_SAFE_RELEASE(_assembler);
_assembler = assembler;
CC_SAFE_RETAIN(_assembler);
auto assemblerSprite = dynamic_cast<AssemblerSprite*>(_assembler);
if (assemblerSprite)
{
*_dirty |= RenderFlow::PRE_CALCULATE_VERTICES;
}
else
{
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
}
}
void NodeProxy::clearAssembler()
{
CC_SAFE_RELEASE_NULL(_assembler);
*_dirty &= ~RenderFlow::PRE_CALCULATE_VERTICES;
}
AssemblerBase* NodeProxy::getAssembler() const
{
return _assembler;
}
void NodeProxy::getPosition(cocos2d::Vec3* out) const
{
out->x = _trs->x;
out->y = _trs->y;
out->z = _trs->z;
}
void NodeProxy::getRotation(cocos2d::Quaternion* out) const
{
out->x = _trs->qx;
out->y = _trs->qy;
out->z = _trs->qz;
out->w = _trs->qw;
}
void NodeProxy::getScale(cocos2d::Vec3* out) const
{
out->x = _trs->sx;
out->y = _trs->sy;
out->z = _trs->sz;
}
void NodeProxy::getWorldRotation(cocos2d::Quaternion* out) const
{
getRotation(out);
cocos2d::Quaternion rot;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getRotation(&rot);
Quaternion::multiply(rot, *out, out);
curr = curr->getParent();
}
}
void NodeProxy::getWorldPosition(cocos2d::Vec3* out) const
{
getPosition(out);
cocos2d::Vec3 pos;
cocos2d::Quaternion rot;
cocos2d::Vec3 scale;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getPosition(&pos);
curr->getRotation(&rot);
curr->getScale(&scale);
out->multiply(scale);
out->transformQuat(rot);
out->add(pos);
curr = curr->getParent();
}
}
void NodeProxy::getWorldRT(cocos2d::Mat4* out) const
{
cocos2d::Vec3 opos(_trs->x, _trs->y, _trs->z);
cocos2d::Quaternion orot(_trs->qx, _trs->qy, _trs->qz, _trs->qw);
cocos2d::Vec3 pos;
cocos2d::Quaternion rot;
cocos2d::Vec3 scale;
NodeProxy* curr = _parent;
while (curr != nullptr)
{
curr->getPosition(&pos);
curr->getRotation(&rot);
curr->getScale(&scale);
opos.multiply(scale);
opos.transformQuat(rot);
opos.add(pos);
Quaternion::multiply(rot, orot, &orot);
curr = curr->getParent();
}
out->setIdentity();
out->translate(opos);
cocos2d::Mat4 quatMat;
cocos2d::Mat4::createRotation(orot, &quatMat);
out->multiply(quatMat);
}
void NodeProxy::setOpacity(uint8_t opacity)
{
if (*_opacity != opacity)
{
*_opacity = opacity;
*_dirty |= RenderFlow::OPACITY;
}
}
void NodeProxy::updateRealOpacity()
{
bool selfOpacityDirty = *_dirty & RenderFlow::OPACITY;
if (_parent)
{
if (selfOpacityDirty || *_parent->_dirty & RenderFlow::NODE_OPACITY_CHANGED)
{
_realOpacity = *_opacity * _parent->getRealOpacity() / 255.0f;
*_dirty &= ~RenderFlow::OPACITY;
*_dirty |= RenderFlow::NODE_OPACITY_CHANGED;
}
}
else
{
if (selfOpacityDirty)
{
_realOpacity = *_opacity;
*_dirty &= ~RenderFlow::OPACITY;
*_dirty |= RenderFlow::NODE_OPACITY_CHANGED;
}
}
}
void NodeProxy::updateWorldMatrix()
{
if (!_updateWorldMatrix) return;
bool selfWorldDirty = *_dirty & RenderFlow::WORLD_TRANSFORM;
if (_parent)
{
if (selfWorldDirty || *_parent->_dirty & RenderFlow::WORLD_TRANSFORM_CHANGED)
{
cocos2d::Mat4::multiply(_parent->getWorldMatrix(), *_localMat, _worldMat);
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
}
else if (selfWorldDirty)
{
*_worldMat = *_localMat;
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
}
void NodeProxy::updateWorldMatrix(const cocos2d::Mat4& worldMatrix)
{
*_worldMat = worldMatrix;
*_dirty &= ~RenderFlow::WORLD_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM_CHANGED;
}
void NodeProxy::updateLocalMatrix()
{
bool skew = std::abs(_skew->x - 0.0f) > MATH_EPSILON || std::abs(_skew->y - 0.0f) > MATH_EPSILON;
if (*_dirty & RenderFlow::LOCAL_TRANSFORM || skew)
{
_localMat->setIdentity();
// Transform = Translate * Rotation * Scale;
cocos2d::Quaternion q(_trs->qx, _trs->qy, _trs->qz, _trs->qw);
if (*_is3DNode)
{
_localMat->translate(_trs->x, _trs->y, _trs->z);
_localMat->rotate(q);
_localMat->scale(_trs->sx, _trs->sy, _trs->sz);
}
else
{
_localMat->translate(_trs->x, _trs->y, 0);
_localMat->rotate(q);
_localMat->scale(_trs->sx, _trs->sy, 1);
}
if (skew)
{
auto& m = _localMat->m;
auto a = m[0];
auto b = m[1];
auto c = m[4];
auto d = m[5];
auto skx = (float)tanf(CC_DEGREES_TO_RADIANS(_skew->x));
auto sky = (float)tanf(CC_DEGREES_TO_RADIANS(_skew->y));
m[0] = a + c * sky;
m[1] = b + d * sky;
m[4] = c + a * skx;
m[5] = d + b * skx;
}
*_dirty &= ~RenderFlow::LOCAL_TRANSFORM;
*_dirty |= RenderFlow::WORLD_TRANSFORM;
}
}
void NodeProxy::render(NodeProxy* node, ModelBatcher* batcher, Scene* scene)
{
node->_renderOrder = _globalRenderOrder++;
if (!node->_needVisit || node->_realOpacity == 0) return;
bool needRender = *node->_dirty & RenderFlow::RENDER;
if (node->_needRender != needRender)
{
if (node->_assembler) node->_assembler->enableDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
node->_needRender = needRender;
}
// pre render
if (node->_assembler && needRender) node->_assembler->handle(node, batcher, scene);
node->reorderChildren();
for (const auto& child : node->_children)
{
auto traverseHandle = child->traverseHandle;
traverseHandle(child, batcher, scene);
}
// post render
bool needPostRender = *(node->_dirty) & RenderFlow::POST_RENDER;
if (node->_assembler && needPostRender) node->_assembler->postHandle(node, batcher, scene);
}
void NodeProxy::visit(NodeProxy* node, ModelBatcher* batcher, Scene* scene)
{
node->_renderOrder = _globalRenderOrder++;
if (!node->_needVisit) return;
node->updateRealOpacity();
if (node->_realOpacity == 0)
{
return;
}
node->updateLocalMatrix();
node->updateWorldMatrix();
bool needRender = *(node->_dirty) & RenderFlow::RENDER;
if (node->_needRender != needRender)
{
if (node->_assembler) node->_assembler->enableDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
node->_needRender = needRender;
}
// pre render
if (node->_assembler && needRender) node->_assembler->handle(node, batcher, scene);
node->reorderChildren();
for (const auto& child : node->_children)
{
visit(child, batcher, scene);
}
// post render
bool needPostRender = *(node->_dirty) & RenderFlow::POST_RENDER;
if (node->_assembler && needPostRender) node->_assembler->postHandle(node, batcher, scene);
}
RENDERER_END

View File

@@ -0,0 +1,369 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <string>
#include <map>
#include "../Macro.h"
#include "base/CCRef.h"
#include "base/ccTypes.h"
#include "base/CCVector.h"
#include "base/CCMap.h"
#include "math/CCMath.h"
#include "assembler/AssemblerBase.hpp"
#include "MemPool.hpp"
#include <functional>
namespace se {
class Object;
}
RENDERER_BEGIN
class ModelBatcher;
class Scene;
struct TRS;
struct ParentInfo;
struct Skew;
/**
* @addtogroup scene
* @{
*/
/**
* @brief NodeProxy is a cpp delegator of js Node.\n
* It synchronize the hierarchy from js node tree, update the transform each frame, and manages assembler which represent the render component.\n
* JS API: renderer.NodeProxy
@code
let node = new cc.Node();
// NodeProxy is automatically created by cc.Node
let proxy = node._proxy;
@endcode
*/
class NodeProxy : public Ref
{
public:
typedef std::function<void(NodeProxy*, ModelBatcher*, Scene*)> TraverseFunc;
/*
* @brief Visit the node but do not transform position.
*/
static void render(NodeProxy* node, ModelBatcher* batcher, Scene* scene);
/*
* @brief Visit the node as a ordinary node but not a root node.
*/
static void visit(NodeProxy* node, ModelBatcher* batcher, Scene* scene);
/*
* @brief Reset global render order.
*/
static void resetGlobalRenderOrder() { _globalRenderOrder = 0; }
/*
* @brief The default constructor.
*/
NodeProxy(std::size_t unitID, std::size_t index, const std::string& id, const std::string& name);
/*
* @brief The destructor.
*/
~NodeProxy();
/*
* @brief destroy node data immediately .
*/
void destroyImmediately();
/*
* @brief If js node has been destroy.
*/
bool isValid() { return _trs != nullptr; }
/// @{
/// @name Hierarchy
/**
* @brief Adds child node proxy to the node proxy.
* @param[in] child A child node proxy pointer.
*/
void addChild(NodeProxy * child);
/**
* @brief Removes child node proxy from the node proxy.
* @param[in] child A child node proxy pointer.
*/
void removeChild(NodeProxy* child);
/**
* @brief Removes all child node proxies from the current one.
*/
void removeAllChildren();
/**
* @brief Update parent by parent unitId and index.
*/
void notifyUpdateParent();
/**
* @brief Sets the node proxy parent.
* @param[in] parent.
*/
inline void setParent(NodeProxy* parent) { _parent = parent; };
/**
* @brief Gets the node proxy parent.
* @return Parent.
*/
inline NodeProxy* getParent() const { return _parent; };
/**
* @brief Gets the node proxy all children.
* @return Children container.
*/
inline const Vector<NodeProxy*>& getChildren() const { return _children; };
/**
* @brief Gets the node proxy child count.
* @return Child count.
*/
inline size_t getChildrenCount() const { return _children.size(); };
/**
* @brief Gets a child node by name.
* @return Child node.
*/
NodeProxy* getChildByName(std::string childName);
/**
* @brief Gets a child node by runtime id.
* @return Child node.
*/
NodeProxy* getChildByID(std::string id);
/**
* @brief Sets the node proxy's local zorder.
* @param[in] zOrder The value of zorder.
*/
void setLocalZOrder(int zOrder);
/// @} end of Hierarchy
/*
* @brief Gets the world matrix.
* @return World matrix.
*/
inline const cocos2d::Mat4& getWorldMatrix() const { return *_worldMat; };
/*
* @brief Gets the local matrix.
* @return Local matrix.
*/
inline const cocos2d::Mat4& getLocalMatrix() const { return *_localMat; };
/*
* @brief Gets the position.
* @param[out] out The position vector
*/
void getPosition(cocos2d::Vec3* out) const;
/*
* @brief Gets the rotation.
* @param[out] out The rotation quaternion.
*/
void getRotation(cocos2d::Quaternion* out) const;
/*
* @brief Gets the scale.
* @param[out] out The scale vector.
*/
void getScale(cocos2d::Vec3* out) const;
/*
* @brief Gets world rotation.
* @param[out] out The rotation quaternion.
*/
void getWorldRotation(cocos2d::Quaternion* out) const;
/*
* @brief Gets the position in world coordinates.
* @param[out] out The world position vector.
*/
void getWorldPosition(cocos2d::Vec3* out) const;
/*
* @brief Gets the matrix contains the world rotation and translation.
* @param[out] out The matrix to store datas.
*/
void getWorldRT(cocos2d::Mat4* out) const;
/**
* @brief Gets the node's opacity.
*/
inline uint8_t getOpacity() const { return *_opacity; };
/**
* @brief Sets the node's opacity.
*/
void setOpacity(uint8_t opacity);
/**
* @brief Updates opacity from parent.
*/
void updateRealOpacity();
/**
* @brief Gets the node's realOpacity.
*/
inline const uint8_t getRealOpacity() const {return _realOpacity;};
/**
* @brief Gets the node's group id, this controls which camera can see the node.
*/
inline int getCullingMask() const { return *_cullingMask; };
/**
* @brief Sets the node's group id.
* @param[in] groupID The group id
*/
inline void setCullingMask(int cullingMask) { *_cullingMask = cullingMask; };
/**
* @brief Gets the node's name.
* This equals to the one in JS node, helps to debug in cpp.
* @return name
*/
inline const std::string& getName() const { return _name; };
/**
* @brief Sets the node's name.
* The name should be updated once JS node's name changes.
* @param[in] name
*/
inline void setName(const std::string& name) { _name = name; };
/**
* @brief Sets the node's 3D state.
* @param[in] is3DNode
*/
inline void set3DNode(bool is3DNode) { *_is3DNode = is3DNode ? 0x1 : 0x0; };
/**
* @brief Sets a system handle to the node proxy, system handle will be invoked during node's visit process.
* @param[in] handle The system handle pointer.
*/
void setAssembler(AssemblerBase* assembler);
/**
* @brief Removes a system handle from node proxy by system id.
* @param[in] sysid The system id.
*/
void clearAssembler();
/**
* @brief Gets the system handle by system id.
* @param[in] sysid The system id.
* @return The system handle object or nullptr if not exist
*/
AssemblerBase* getAssembler() const;
/*
* @brief Enables visit.
*/
void enableVisit(bool value) { _needVisit = value; }
/*
* @brief Disables visit.
*/
void disableVisit() { _needVisit = false; }
/*
* @brief Updates local matrix.
*/
void updateLocalMatrix();
/*
* @brief Updates world matrix.
*/
void updateWorldMatrix();
/*
* @brief Updates world matrix with provide matrix.
*/
void updateWorldMatrix(const cocos2d::Mat4& worldMatrix);
/*
* @brief Enables calc world matrix.
*/
void enableUpdateWorldMatrix(bool value) { _updateWorldMatrix = value; }
/*
* @brief Gets node runtime id
*/
const std::string& getID() const { return _id; }
/*
* @brief Gets node dirty
*/
uint32_t* getDirty() const { return _dirty; }
/*
* @brief Is node flag dirty
*/
bool isDirty(uint32_t flag) const { return *_dirty & flag; }
/*
* @brief Gets render order
*/
uint32_t getRenderOrder () { return _renderOrder; }
/*
* @brief switch traverse interface to visit
*/
void switchTraverseToVisit() { traverseHandle = visit; }
/*
* @brief switch traverse interface to render
*/
void switchTraverseToRender() { traverseHandle = render; }
/*
* @brief traverse handle
*/
TraverseFunc traverseHandle = nullptr;
protected:
void updateLevel();
void childrenAlloc();
void detachChild(NodeProxy* child, ssize_t childIndex);
void reorderChildren();
private:
bool _needVisit = true;
bool _updateWorldMatrix = true;
bool _needRender = false;
uint8_t _realOpacity = 255;
std::string _id = "";
std::string _name = "";
std::size_t _level = 0;
uint32_t* _dirty = nullptr;
TRS* _trs = nullptr;
cocos2d::Mat4* _localMat = nullptr;
cocos2d::Mat4* _worldMat = nullptr;
ParentInfo* _parentInfo = nullptr;
int32_t* _localZOrder = nullptr;
int32_t* _cullingMask = nullptr;
uint8_t* _opacity = nullptr;
uint8_t* _is3DNode = nullptr;
Skew* _skew = nullptr;
std::size_t _unitID = 0;
std::size_t _index = 0;
Sign* _signData = nullptr;
NodeProxy* _parent = nullptr; ///< weak reference to parent node
cocos2d::Vector<NodeProxy*> _children; ///< array of children nodes
AssemblerBase* _assembler = nullptr;
uint32_t _renderOrder = 0;
static uint32_t _globalRenderOrder;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,176 @@
/****************************************************************************
Copyright (c) 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 "ParallelTask.hpp"
RENDERER_BEGIN
ParallelTask::ParallelTask()
{
}
ParallelTask::~ParallelTask()
{
destroy();
}
void ParallelTask::init(int threadNum)
{
_finished = false;
_threadNum = threadNum;
_tasks.resize(_threadNum);
_threads.resize(_threadNum);
_runFlags = new uint8_t[_threadNum];
memset(_runFlags, RunFlag::Stop, sizeof(uint8_t) * _threadNum);
for(auto i = 0; i < _threadNum; i++)
{
setThread(i);
}
}
void ParallelTask::pushTask(int tid, const Task& task)
{
if (tid >= 0 && tid < _tasks.size())
{
_tasks[tid].push_back(task);
}
}
void ParallelTask::clearTasks()
{
for(std::size_t i = 0, n = _tasks.size(); i < n; i++)
{
_tasks[i].clear();
}
}
uint8_t* ParallelTask::getRunFlag()
{
return _runFlags;
}
void ParallelTask::destroy()
{
_finished = true;
beginAllThreads();
for (int i = 0, n = (int)_threads.size(); i < n; ++i)
{
joinThread(i);
}
_tasks.clear();
_threads.clear();
delete _runFlags;
_runFlags = nullptr;
_threadNum = 0;
}
void ParallelTask::stopAllThreads()
{
if (!_runFlags) return;
memset(_runFlags, RunFlag::Stop, sizeof(uint8_t) * _threadNum);
}
void ParallelTask::beginAllThreads()
{
if (!_runFlags) return;
memset(_runFlags, RunFlag::Begin, sizeof(uint8_t) * _threadNum);
{
std::unique_lock<std::mutex> lock(_mutex);
_cv.notify_all();
}
}
void ParallelTask::waitAllThreads()
{
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, [this]() {
if (!_runFlags) return true;
for (auto i = 0; i < _threadNum; i++)
{
if (_runFlags[i] == RunFlag::Begin) return false;
}
return true;
});
}
void ParallelTask::joinThread(int tid)
{
if (tid < 0 || tid >= (int)_threads.size())
{
return;
}
if (_threads[tid]->joinable())
{
_threads[tid]->join();
}
}
void ParallelTask::setThread(int tid)
{
auto f = [this, tid]() {
uint8_t& runFlag = _runFlags[tid];
if (!runFlag) return;
auto& taskQueue = _tasks[tid];
std::size_t idx = 0;
std::size_t taskCount = 0;
while (!_finished)
{
switch (runFlag)
{
case RunFlag::Begin:
for (idx = 0, taskCount = taskQueue.size(); idx < taskCount; idx++)
{
const Task& task = taskQueue[idx];
task(tid);
}
runFlag = RunFlag::Stop;
{
std::unique_lock<std::mutex> lock(_mutex);
_cv.notify_all();
}
break;
case RunFlag::Stop:
{
std::unique_lock<std::mutex> lock(_mutex);
_cv.wait(lock, [this, &runFlag]()
{
return runFlag == RunFlag::Begin || _finished;
});
}
break;
}
}
};
_threads[tid].reset(new(std::nothrow) std::thread(f));
}
RENDERER_END

View File

@@ -0,0 +1,78 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../Macro.h"
#include <vector>
#include <stdint.h>
#include <functional>
#include <thread>
#include <memory>
#include <condition_variable>
#include <mutex>
RENDERER_BEGIN
class ParallelTask
{
public:
enum RunFlag{
Begin = 0x00,
Stop = 0x01,
};
typedef std::function<void(int)> Task;
ParallelTask();
virtual ~ParallelTask();
void pushTask(int tid, const Task& task);
void clearTasks();
uint8_t* getRunFlag();
void init(int threadNum);
void destroy();
void waitAllThreads();
void stopAllThreads();
void beginAllThreads();
private:
void joinThread(int tid);
void setThread(int tid);
private:
std::vector<std::vector<Task>> _tasks;
std::vector<std::unique_ptr<std::thread>> _threads;
uint8_t* _runFlags = nullptr;
bool _finished = false;
int _threadNum = 0;
std::mutex _mutex;
std::condition_variable _cv;
};
RENDERER_END

View File

@@ -0,0 +1,379 @@
/****************************************************************************
Copyright (c) 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 "RenderFlow.hpp"
#include "NodeMemPool.hpp"
#include "assembler/AssemblerSprite.hpp"
#if USE_MIDDLEWARE
#include "MiddlewareManager.h"
#endif
#define SUB_RENDER_THREAD_COUNT 1
#define RENDER_THREAD_COUNT (SUB_RENDER_THREAD_COUNT + 1)
RENDERER_BEGIN
const uint32_t InitLevelCount = 3;
const uint32_t InitLevelNodeCount = 100;
const uint32_t LocalMat_Use_Thread_Unit_Count = 5;
const uint32_t WorldMat_Use_Thread_Node_count = 500;
RenderFlow* RenderFlow::_instance = nullptr;
RenderFlow::RenderFlow(DeviceGraphics* device, Scene* scene, ForwardRenderer* forward)
: _device(device)
, _scene(scene)
, _forward(forward)
{
_instance = this;
_batcher = new ModelBatcher(this);
#if SUB_RENDER_THREAD_COUNT > 0
_paralleTask = new ParallelTask();
_paralleTask->init(SUB_RENDER_THREAD_COUNT);
for (uint32_t i = 0; i < SUB_RENDER_THREAD_COUNT; i++)
{
_paralleTask->pushTask(i, [this](int tid){
switch(_parallelStage)
{
case ParallelStage::LOCAL_MAT:
calculateLocalMatrix(tid);
break;
case ParallelStage::WORLD_MAT:
calculateLevelWorldMatrix(tid, _parallelStage);
break;
default:
break;
}
});
}
#endif
_levelInfoArr.resize(InitLevelCount);
for (auto i = 0; i < InitLevelCount; i++)
{
_levelInfoArr[i].reserve(InitLevelNodeCount);
}
}
RenderFlow::~RenderFlow()
{
CC_SAFE_DELETE(_paralleTask);
CC_SAFE_DELETE(_batcher);
}
void RenderFlow::removeNodeLevel(std::size_t level, cocos2d::Mat4* worldMat)
{
if (level >= _levelInfoArr.size()) return;
auto& levelInfos = _levelInfoArr[level];
for(auto it = levelInfos.begin(); it != levelInfos.end(); it++)
{
if (it->worldMat == worldMat)
{
levelInfos.erase(it);
return;
}
}
}
void RenderFlow::insertNodeLevel(std::size_t level, const LevelInfo& levelInfo)
{
if (level >= _levelInfoArr.size())
{
_levelInfoArr.resize(level + 1);
}
auto& levelInfos = _levelInfoArr[level];
levelInfos.push_back(levelInfo);
}
void RenderFlow::calculateLocalMatrix(int tid)
{
const uint16_t SPACE_FREE_FLAG = 0x0;
cocos2d::Mat4 matTemp;
NodeMemPool* instance = NodeMemPool::getInstance();
CCASSERT(instance, "RenderFlow calculateLocalMatrix NodeMemPool is null");
auto& commonList = instance->getCommonList();
auto& nodePool = instance->getNodePool();
UnitCommon* commonUnit = nullptr;
uint16_t usingNum = 0;
std::size_t contentNum = 0;
Sign* signData = nullptr;
UnitNode* nodeUnit = nullptr;
uint32_t* dirty = nullptr;
cocos2d::Mat4* localMat = nullptr;
TRS* trs = nullptr;
uint8_t* is3D = nullptr;
cocos2d::Quaternion* quat = nullptr;
float trsZ = 0.0f, trsSZ = 0.0f;
std::size_t begin = 0, end = commonList.size();
std::size_t fieldSize = end / RENDER_THREAD_COUNT;
if (tid >= 0)
{
begin = tid * fieldSize;
if (tid < RENDER_THREAD_COUNT - 1)
{
end = (tid + 1) * fieldSize;
}
}
for(auto i = begin; i < end; i++)
{
commonUnit = commonList[i];
if (!commonUnit) continue;
usingNum = commonUnit->getUsingNum();
if (usingNum == 0) continue;
contentNum = commonUnit->getContentNum();
signData = commonUnit->getSignData(0);
nodeUnit = nodePool[commonUnit->unitID];
dirty = nodeUnit->getDirty(0);
localMat = nodeUnit->getLocalMat(0);
trs = nodeUnit->getTRS(0);
is3D = nodeUnit->getIs3D(0);
NodeProxy** nodeProxy = (NodeProxy**)nodeUnit->getNode(0);
for (auto j = 0; j < contentNum; j++, localMat ++, trs ++, is3D ++, signData++, dirty++, nodeProxy++)
{
if (signData->freeFlag == SPACE_FREE_FLAG) continue;
// reset world transform changed flag
*dirty &= ~(WORLD_TRANSFORM_CHANGED | NODE_OPACITY_CHANGED);
if (!(*dirty & LOCAL_TRANSFORM)) continue;
localMat->setIdentity();
trsZ = *is3D ? trs->z : 0;
localMat->translate(trs->x, trs->y, trsZ);
quat = (cocos2d::Quaternion*)&(trs->qx);
cocos2d::Mat4::createRotation(*quat, &matTemp);
cocos2d::Mat4::multiply(*localMat, matTemp, localMat);
trsSZ = *is3D ? trs->sz : 1;
cocos2d::Mat4::createScale(trs->sx, trs->sy, trsSZ, &matTemp);
cocos2d::Mat4::multiply(*localMat, matTemp, localMat);
*dirty &= ~LOCAL_TRANSFORM;
*dirty |= WORLD_TRANSFORM;
}
}
}
void RenderFlow::calculateLevelWorldMatrix(int tid, int stage)
{
if (_curLevel >= _levelInfoArr.size())
{
return;
}
auto& levelInfos = _levelInfoArr[_curLevel];
std::size_t begin = 0, end = levelInfos.size();
std::size_t fieldSize = end / RENDER_THREAD_COUNT;
if (tid >= 0)
{
begin = tid * fieldSize;
if (tid < RENDER_THREAD_COUNT - 1)
{
end = (tid + 1) * fieldSize;
}
}
for(std::size_t index = begin; index < end; index++)
{
auto& info = levelInfos[index];
auto dirty = info.dirty;
auto parentDirty = info.parentDirty;
auto selfWorldDirty = *dirty & WORLD_TRANSFORM;
auto selfOpacityDirty = *dirty & OPACITY;
if (parentDirty)
{
if ((*parentDirty & WORLD_TRANSFORM_CHANGED) || selfWorldDirty)
{
cocos2d::Mat4::multiply(*info.parentWorldMat, *info.localMat, info.worldMat);
*dirty |= WORLD_TRANSFORM_CHANGED;
*dirty &= ~WORLD_TRANSFORM;
}
if ((*parentDirty & NODE_OPACITY_CHANGED) || selfOpacityDirty)
{
*info.realOpacity = *info.opacity * *info.parentRealOpacity / 255.0f;
*dirty |= NODE_OPACITY_CHANGED;
*dirty &= ~OPACITY;
}
}
else
{
if (selfWorldDirty)
{
*info.worldMat = *info.localMat;
*dirty |= WORLD_TRANSFORM_CHANGED;
*dirty &= ~WORLD_TRANSFORM;
}
if (selfOpacityDirty)
{
*info.realOpacity = *info.opacity;
*dirty |= NODE_OPACITY_CHANGED;
*dirty &= ~OPACITY;
}
}
}
}
void RenderFlow::calculateWorldMatrix()
{
for(std::size_t level = 0, n = _levelInfoArr.size(); level < n; level++)
{
auto& levelInfos = _levelInfoArr[level];
for(std::size_t index = 0, count = levelInfos.size(); index < count; index++)
{
auto& info = levelInfos[index];
auto selfWorldDirty = *info.dirty & WORLD_TRANSFORM;
auto selfOpacityDirty = *info.dirty & OPACITY;
if (info.parentDirty)
{
if ((*info.parentDirty & WORLD_TRANSFORM_CHANGED) || selfWorldDirty)
{
cocos2d::Mat4::multiply(*info.parentWorldMat, *info.localMat, info.worldMat);
*info.dirty |= WORLD_TRANSFORM_CHANGED;
*info.dirty &= ~WORLD_TRANSFORM;
}
if ((*info.parentDirty & NODE_OPACITY_CHANGED) || selfOpacityDirty)
{
*info.realOpacity = *info.opacity * *info.parentRealOpacity / 255.0f;
*info.dirty |= NODE_OPACITY_CHANGED;
*info.dirty &= ~OPACITY;
}
}
else
{
if (selfWorldDirty)
{
*info.worldMat = *info.localMat;
*info.dirty |= WORLD_TRANSFORM_CHANGED;
*info.dirty &= ~WORLD_TRANSFORM;
}
if (selfOpacityDirty)
{
*info.realOpacity = *info.opacity;
*info.dirty |= NODE_OPACITY_CHANGED;
*info.dirty &= ~OPACITY;
}
}
}
}
}
void RenderFlow::render(NodeProxy* scene, float deltaTime, Camera *camera)
{
if (scene != nullptr)
{
#if USE_MIDDLEWARE
// udpate middleware before render
middleware::MiddlewareManager::getInstance()->update(deltaTime);
#endif
#if SUB_RENDER_THREAD_COUNT > 0
int mainThreadTid = RENDER_THREAD_COUNT - 1;
NodeMemPool* instance = NodeMemPool::getInstance();
auto& commonList = instance->getCommonList();
if (commonList.size() < LocalMat_Use_Thread_Unit_Count)
{
_parallelStage = ParallelStage::NONE;
calculateLocalMatrix();
}
else
{
_parallelStage = ParallelStage::LOCAL_MAT;
_paralleTask->beginAllThreads();
calculateLocalMatrix(mainThreadTid);
_paralleTask->waitAllThreads();
}
_curLevel = 0;
for(auto count = _levelInfoArr.size(); _curLevel < count; _curLevel++)
{
auto& levelInfos = _levelInfoArr[_curLevel];
if (levelInfos.size() < WorldMat_Use_Thread_Node_count)
{
_parallelStage = ParallelStage::NONE;
calculateLevelWorldMatrix();
}
else
{
_parallelStage = ParallelStage::WORLD_MAT;
_paralleTask->beginAllThreads();
calculateLevelWorldMatrix(mainThreadTid);
_paralleTask->waitAllThreads();
}
}
#else
calculateLocalMatrix();
calculateWorldMatrix();
#endif
_batcher->startBatch();
#if USE_MIDDLEWARE
// render middleware
middleware::MiddlewareManager::getInstance()->render(deltaTime);
#endif
scene->resetGlobalRenderOrder();
auto traverseHandle = scene->traverseHandle;
traverseHandle(scene, _batcher, _scene);
_batcher->terminateBatch();
if (camera) {
_forward->renderCamera(camera, _scene);
}
else {
_forward->render(_scene, deltaTime);
}
}
}
void RenderFlow::visit(NodeProxy* rootNode)
{
NodeProxy::visit(rootNode, _batcher, _scene);
}
RENDERER_END

View File

@@ -0,0 +1,180 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../Macro.h"
#include "NodeProxy.hpp"
#include "ModelBatcher.hpp"
#include "../renderer/Scene.h"
#include "../renderer/ForwardRenderer.h"
#include "../gfx/DeviceGraphics.h"
#include "ParallelTask.hpp"
RENDERER_BEGIN
/**
* @addtogroup scene
* @{
*/
/**
* @brief This class is responsible for the rendering process.\n
* It visits the node tree, let nodes commit their render handles, starts the device level rendering process with ForwardRenderer.\n
* JS API: renderer.RenderFlow
@code
// You actually shouldn't create RenderFlow by yourself, you can
let renderFlow = cc.RenderFlow._nativeFlow;
@endcode
*/
#define NODE_LEVEL_INVALID 0xffffffff
class RenderFlow
{
public:
enum RenderFlowFlag {
// sync js render flag
DONOTHING = 1 << 0,
BREAK_FLOW = 1 << 1,
LOCAL_TRANSFORM = 1 << 2,
WORLD_TRANSFORM = 1 << 3,
TRANSFORM = LOCAL_TRANSFORM | WORLD_TRANSFORM,
UPDATE_RENDER_DATA = 1 << 4,
OPACITY = 1 << 5,
COLOR = 1 << 6,
RENDER = 1 << 7,
CHILDREN = 1 << 8,
POST_RENDER = 1 << 9,
FINAL = 1 << 10,
PRE_CALCULATE_VERTICES = 1 << 28,
// native render flag
REORDER_CHILDREN = 1 << 29,
// world matrix changed
WORLD_TRANSFORM_CHANGED = 1 << 30,
// cascade opacity changed
NODE_OPACITY_CHANGED = 1 << 31,
};
enum ParallelStage {
NONE = 1 << 0,
LOCAL_MAT = 1 << 1,
WORLD_MAT = 1 << 2,
CALC_VERTICES = 1 << 3,
};
struct LevelInfo{
uint32_t* dirty = nullptr;
uint32_t* parentDirty = nullptr;
cocos2d::Mat4* parentWorldMat = nullptr;
uint8_t* parentRealOpacity = nullptr;
cocos2d::Mat4* localMat = nullptr;
cocos2d::Mat4* worldMat = nullptr;
uint8_t* opacity = nullptr;
uint8_t* realOpacity = nullptr;
};
static RenderFlow *getInstance()
{
return _instance;
}
/*
* @brief The constructor.
* @param[in] device
* @param[in] scene
* @param[in] forward
*/
RenderFlow(DeviceGraphics* device, Scene* scene, ForwardRenderer* forward);
/*
* @brief The destructor.
*/
~RenderFlow();
/*
* @brief Gets the ModelBatcher which is responsible for collecting render Models.
*/
ModelBatcher* getModelBatcher() const { return _batcher; };
/*
* @brief Gets the DeviceGraphics using by the current RenderFlow.
*/
DeviceGraphics* getDevice() const { return _device; };
/*
* @brief Gets the render Scene which manages all render Models.
*/
Scene* getRenderScene() const { return _scene; };
/**
* @brief Render the scene specified by its root node.
* @param[in] scene The root node.
*/
void render(NodeProxy* scene, float deltaTime, Camera *camera = nullptr);
/**
* @brief Visit a node tree.
*/
void visit(NodeProxy* rootNode);
/**
* @brief Calculate local matrix.
* @param[in] tid It must rather than -1 if enable multiple thread.
*/
void calculateLocalMatrix(int tid = -1);
/**
* @brief Calculate world matrix.
*/
void calculateWorldMatrix();
/**
* @brief Calculate world matrix by level.
* @param[in] tid Thread id.
* @param[level] level Node level.
*/
void calculateLevelWorldMatrix(int tid = -1, int stage = -1);
/**
* @brief remove node level
*/
void removeNodeLevel(std::size_t level, cocos2d::Mat4* worldMat);
/**
* @brief insert node level
*/
void insertNodeLevel(std::size_t level, const LevelInfo& levelInfo);
private:
static RenderFlow *_instance;
ModelBatcher* _batcher = nullptr;
Scene* _scene = nullptr;
DeviceGraphics* _device = nullptr;
ForwardRenderer* _forward = nullptr;
std::size_t _curLevel = 0;
std::vector<std::vector<LevelInfo>> _levelInfoArr;
ParallelStage _parallelStage = ParallelStage::NONE;
ParallelTask* _paralleTask = nullptr;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,184 @@
/****************************************************************************
Copyright (c) 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 "StencilManager.hpp"
#include "../Types.h"
#include "../renderer/Technique.h"
#include "../renderer/Pass.h"
RENDERER_BEGIN
static const std::string techStage = "opaque";
StencilManager* StencilManager::_instance = nullptr;
StencilManager::StencilManager ()
: _stage(Stage::DISABLED)
{
}
StencilManager::~StencilManager ()
{
}
void StencilManager::reset ()
{
// reset stack and stage
_maskStack.clear();
_stage = Stage::DISABLED;
}
EffectVariant* StencilManager::handleEffect (EffectVariant* effect)
{
Vector<Pass*>& passes = (Vector<Pass*>&)effect->getPasses();
if (_stage == Stage::DISABLED)
{
for (const auto& pass : passes)
{
if (pass->isStencilTest()) {
pass->disableStencilTest();
}
}
return effect;
}
auto size = _maskStack.size();
if (size == 0 || size == size_t(-1))
{
return effect;
}
uint32_t ref;
uint8_t stencilMask, writeMask;
bool mask;
StencilFunc func;
StencilOp failOp = StencilOp::KEEP;
const StencilOp& zFailOp = StencilOp::KEEP;
const StencilOp& zPassOp = StencilOp::KEEP;
if (_stage == Stage::ENABLED)
{
mask = _maskStack.back();
func = StencilFunc::EQUAL;
failOp = StencilOp::KEEP;
ref = getStencilRef();
stencilMask = ref;
writeMask = getWriteMask();
}
else {
if (_stage == Stage::CLEAR) {
mask = _maskStack.back();
func = StencilFunc::NEVER;
failOp = mask ? StencilOp::REPLACE : StencilOp::ZERO;
ref = getWriteMask();
stencilMask = ref;
writeMask = ref;
}
else if (_stage == Stage::ENTER_LEVEL) {
mask = _maskStack.back();
// Fill stencil mask
func = StencilFunc::NEVER;
failOp = mask ? StencilOp::ZERO : StencilOp::REPLACE;
ref = getWriteMask();
stencilMask = ref;
writeMask = ref;
}
}
for (const auto& pass : passes) {
pass->setStencilFront(func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask);
pass->setStencilBack(func, ref, stencilMask, failOp, zFailOp, zPassOp, writeMask);
}
return effect;
}
void StencilManager::pushMask (bool mask)
{
if (_maskStack.size() + 1 > _maxLevel)
{
cocos2d::log("StencilManager:pushMask _maxLevel:%d is out of range", _maxLevel);
}
_maskStack.push_back(mask);
}
void StencilManager::clear ()
{
_stage = Stage::CLEAR;
}
void StencilManager::enterLevel ()
{
_stage = Stage::ENTER_LEVEL;
}
void StencilManager::enableMask ()
{
_stage = Stage::ENABLED;
}
void StencilManager::exitMask ()
{
if (_maskStack.size() == 0) {
cocos2d::log("StencilManager:exitMask _maskStack:%zu size is 0", _maskStack.size());
}
_maskStack.pop_back();
if (_maskStack.size() == 0) {
_stage = Stage::DISABLED;
}
else {
_stage = Stage::ENABLED;
}
}
uint8_t StencilManager::getWriteMask ()
{
return 0x01 << (_maskStack.size() - 1);
}
uint8_t StencilManager::getExitWriteMask ()
{
return 0x01 << _maskStack.size();
}
uint32_t StencilManager::getStencilRef ()
{
int32_t result = 0;
size_t size = _maskStack.size();
for (int i = 0; i < size; ++i) {
result += (0x01 << i);
}
return result;
}
uint32_t StencilManager::getInvertedRef ()
{
int32_t result = 0;
size_t size = _maskStack.size();
for (int i = 0; i < size - 1; ++i)
{
result += (0x01 << i);
}
return result;
}
RENDERER_END

View File

@@ -0,0 +1,113 @@
/****************************************************************************
LICENSING AGREEMENT
Xiamen Yaji Software Co., Ltd., (the “Licensor”) grants the user (the “Licensee”) non-exclusive and non-transferable rights to use the software according to the following conditions:
a. The Licensee shall pay royalties to the Licensor, and the amount of those royalties and the payment method are subject to separate negotiations between the parties.
b. The software is licensed for use rather than sold, and the Licensor reserves all rights over the software that are not expressly granted (whether by implication, reservation or prohibition).
c. The open source codes contained in the software are subject to the MIT Open Source Licensing Agreement (see the attached for the details);
d. The Licensee acknowledges and consents to the possibility that errors may occur during the operation of the software for one or more technical reasons, and the Licensee shall take precautions and prepare remedies for such events. In such circumstance, the Licensor shall provide software patches or updates according to the agreement between the two parties. The Licensor will not assume any liability beyond the explicit wording of this Licensing Agreement.
e. Where the Licensor must assume liability for the software according to relevant laws, the Licensors entire liability is limited to the annual royalty payable by the Licensee.
f. The Licensor owns the portions listed in the root directory and subdirectory (if any) in the software and enjoys the intellectual property rights over those portions. As for the portions owned by the Licensor, the Licensee shall not:
- i. Bypass or avoid any relevant technical protection measures in the products or services;
- ii. Release the source codes to any other parties;
- iii. Disassemble, decompile, decipher, attack, emulate, exploit or reverse-engineer these portion of code;
- iv. Apply it to any third-party products or services without Licensors permission;
- v. Publish, copy, rent, lease, sell, export, import, distribute or lend any products containing these portions of code;
- vi. Allow others to use any services relevant to the technology of these codes;
- vii. Conduct any other act beyond the scope of this Licensing Agreement.
g. This Licensing Agreement terminates immediately if the Licensee breaches this Agreement. The Licensor may claim compensation from the Licensee where the Licensees breach causes any damage to the Licensor.
h. The laws of the People's Republic of China apply to this Licensing Agreement.
i. This Agreement is made in both Chinese and English, and the Chinese version shall prevail the event of conflict.
****************************************************************************/
#pragma once
#include <stdio.h>
#include <vector>
#include "../../base/CCVector.h"
#include "renderer/EffectVariant.hpp"
RENDERER_BEGIN
/**
* @addtogroup scene
* @{
*/
// Stage types
enum class Stage{
// Stencil disabled
DISABLED = 0,
// Clear stencil buffer
CLEAR = 1,
// Entering a new level, should handle new stencil
ENTER_LEVEL = 2,
// In content
ENABLED = 3,
// Exiting a level, should restore old stencil or disable
EXIT_LEVEL = 4
};
/**
* The stencil manager post process the Effect in Model to make them apply correct stencil states
* After activated a stencil mask and before desactivated it, all Models committed in between should apply the stencil's states in the Pass of Effect.
* This is a singleton class mainly used by ModelBatcher.
*/
class StencilManager
{
public:
StencilManager();
~StencilManager();
/**
* Reset all states
*/
void reset();
/**
* Apply correct stencil states to the Effect
*/
EffectVariant* handleEffect(EffectVariant* effect);
/**
* Add a mask to the stack
*/
void pushMask(bool mask);
/**
* Stage for clearing the stencil buffer for the last mask
*/
void clear();
/**
* Enters a new mask level, this stage is for drawing the stencil ref to the stencil buffer.
*/
void enterLevel();
/**
* Enables the current mask, this stage is for applying stencil states defined by the current mask.
*/
void enableMask();
/**
* Exits a mask level
*/
void exitMask();
uint8_t getWriteMask();
uint8_t getExitWriteMask();
uint32_t getStencilRef();
uint32_t getInvertedRef();
static StencilManager* getInstance()
{
if (_instance == nullptr)
{
_instance = new StencilManager;
}
return _instance;
}
private:
const int _maxLevel = 8;
std::vector<bool> _maskStack;
Stage _stage;
static StencilManager* _instance;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,285 @@
/****************************************************************************
Copyright (c) 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 "Assembler.hpp"
#include "../NodeProxy.hpp"
#include "../ModelBatcher.hpp"
#include "../MeshBuffer.hpp"
#include "../../renderer/Scene.h"
#include "math/CCMath.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
#include "cocos/scripting/js-bindings/manual/jsb_conversions.hpp"
#include "cocos/scripting/js-bindings/auto/jsb_renderer_auto.hpp"
#include "../RenderFlow.hpp"
RENDERER_BEGIN
Assembler::IARenderData::IARenderData()
{
}
Assembler::IARenderData::IARenderData(const IARenderData& o)
{
meshIndex = o.meshIndex;
verticesStart = o.verticesStart;
verticesCount = o.verticesCount;
indicesStart = o.indicesStart;
indicesCount = o.indicesCount;
setEffect(o.getEffect());
}
Assembler::IARenderData::~IARenderData()
{
CC_SAFE_RELEASE(_effect);
}
void Assembler::IARenderData::setEffect(EffectVariant* effect)
{
if (effect == _effect) return;
CC_SAFE_RELEASE(_effect);
_effect = effect;
CC_SAFE_RETAIN(_effect);
}
EffectVariant* Assembler::IARenderData::getEffect() const
{
return _effect;
}
Assembler::Assembler()
{
}
Assembler::~Assembler()
{
CC_SAFE_RELEASE_NULL(_datas);
CC_SAFE_RELEASE(_vfmt);
}
void Assembler::updateMeshIndex(std::size_t iaIndex, int meshIndex)
{
if (iaIndex >= _iaDatas.size())
{
_iaDatas.resize(iaIndex + 1);
}
IARenderData& ia = _iaDatas[iaIndex];
ia.meshIndex = meshIndex;
}
void Assembler::updateIndicesRange(std::size_t iaIndex, int start, int count)
{
if (iaIndex >= _iaDatas.size())
{
_iaDatas.resize(iaIndex + 1);
}
IARenderData& ia = _iaDatas[iaIndex];
ia.indicesStart = start;
ia.indicesCount = count;
}
void Assembler::updateVerticesRange(std::size_t iaIndex, int start, int count)
{
if (iaIndex >= _iaDatas.size())
{
_iaDatas.resize(iaIndex + 1);
}
IARenderData& ia = _iaDatas[iaIndex];
ia.verticesStart = start;
ia.verticesCount = count;
enableDirty(AssemblerBase::VERTICES_OPACITY_CHANGED);
}
void Assembler::updateEffect(std::size_t iaIndex, EffectVariant* effect)
{
if (iaIndex >= _iaDatas.size())
{
_iaDatas.resize(iaIndex + 1);
}
IARenderData& ia = _iaDatas[iaIndex];
ia.setEffect(effect);
}
void Assembler::reset()
{
_iaDatas.clear();
}
void Assembler::handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene)
{
batcher->commit(node, this, node->getCullingMask());
}
void Assembler::fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index)
{
if(!_datas || !_vfmt)
{
return;
}
MeshBuffer* buffer = batcher->getBuffer(_vfmt);
const IARenderData& ia = _iaDatas[index];
std::size_t meshIndex = ia.meshIndex >= 0 ? ia.meshIndex : index;
RenderData* data = _datas->getRenderData(meshIndex);
if (!data)
{
return;
}
CCASSERT(data->getVBytes() % _bytesPerVertex == 0, "Assembler::fillBuffers vertices data doesn't follow vertex format");
uint32_t vertexCount = ia.verticesCount >= 0 ? (uint32_t)ia.verticesCount : (uint32_t)data->getVBytes() / _bytesPerVertex;
uint32_t indexCount = ia.indicesCount >= 0 ? (uint32_t)ia.indicesCount : (uint32_t)data->getIBytes() / sizeof(unsigned short);
uint32_t vertexStart = (uint32_t)ia.verticesStart;
// must retrieve offset before request
auto& bufferOffset = buffer->request(vertexCount, indexCount);
uint32_t vBufferOffset = bufferOffset.vByte / sizeof(float);
uint32_t indexId = bufferOffset.index;
uint32_t vertexId = bufferOffset.vertex;
uint32_t vertexOffset = vertexId - vertexStart;
uint32_t num = _vfPos->num;
float* worldVerts = buffer->vData + vBufferOffset;
memcpy(worldVerts, data->getVertices() + vertexStart * _bytesPerVertex, vertexCount * _bytesPerVertex);
// Calculate vertices world positions
if (!_useModel && !_ignoreWorldMatrix)
{
size_t dataPerVertex = _bytesPerVertex / sizeof(float);
float* ptrPos = worldVerts + _posOffset;
auto& worldMat = node->getWorldMatrix();
switch (num) {
// Vertex is X Y Z Format
case 3:
for (uint32_t i = 0; i < vertexCount; ++i)
{
((cocos2d::Vec3*)ptrPos)->transformMat4(*((cocos2d::Vec3*)ptrPos), worldMat);
ptrPos += dataPerVertex;
}
break;
// Vertex is X Y Format
case 2:
for (uint32_t i = 0; i < vertexCount; ++i)
{
float z = ptrPos[2];
ptrPos[2] = 0;
worldMat.transformPoint((cocos2d::Vec3*)ptrPos);
ptrPos[2] = z;
ptrPos += dataPerVertex;
}
break;
}
}
// Copy index buffer with vertex offset
uint16_t* indices = (uint16_t*)data->getIndices();
uint16_t* dst = buffer->iData;
for (auto i = 0, j = ia.indicesStart; i < indexCount; ++i, ++j)
{
dst[indexId++] = vertexOffset + indices[j];
}
}
void Assembler::setVertexFormat(VertexFormat* vfmt)
{
if (_vfmt == vfmt) return;
CC_SAFE_RETAIN(vfmt);
CC_SAFE_RELEASE(_vfmt);
_vfmt = vfmt;
if (_vfmt)
{
_bytesPerVertex = _vfmt->getBytes();
_vfPos = _vfmt->getElement(ATTRIB_NAME_POSITION_HASH);
_posOffset = _vfPos->offset / 4;
_vfColor = _vfmt->getElement(ATTRIB_NAME_COLOR_HASH);
if (_vfColor != nullptr)
{
_alphaOffset = _vfColor->offset + 3;
}
}
}
void Assembler::setRenderDataList(RenderDataList* datas)
{
if (_datas == datas) return;
CC_SAFE_RELEASE(_datas);
_datas = datas;
CC_SAFE_RETAIN(_datas);
}
void Assembler::updateOpacity(std::size_t index, uint8_t opacity)
{
// has no color info in vertex buffer
if(!_vfColor || !_datas || !_vfmt)
{
return;
}
const IARenderData& ia = _iaDatas[index];
std::size_t meshIndex = ia.meshIndex >= 0 ? ia.meshIndex : index;
RenderData* data = _datas->getRenderData(meshIndex);
if (!data)
{
return;
}
CCASSERT(data->getVBytes() % _bytesPerVertex == 0, "Assembler::updateOpacity vertices data doesn't follow vertex format");
uint32_t vertexCount = (uint32_t)data->getVBytes() / _bytesPerVertex;
size_t dataPerVertex = _bytesPerVertex / sizeof(uint8_t);
uint8_t* ptrAlpha = (uint8_t*)data->getVertices() + _alphaOffset;
const Vector<Pass*>& passes = ia.getEffect()->getPasses();
if (passes.at(0)->getBlendSrc() == BlendFactor::ONE)
{
float alpha = opacity / 255.0;
for (uint32_t i = 0; i < vertexCount; ++i)
{
*(ptrAlpha-1) *= alpha;
*(ptrAlpha-2) *= alpha;
*(ptrAlpha-3) *= alpha;
*ptrAlpha = opacity;
ptrAlpha += dataPerVertex;
}
}
else
{
for (uint32_t i = 0; i < vertexCount; ++i)
{
*ptrAlpha = opacity;
ptrAlpha += dataPerVertex;
}
}
*_dirty &= ~VERTICES_OPACITY_CHANGED;
}
RENDERER_END

View File

@@ -0,0 +1,202 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include "AssemblerBase.hpp"
#include "../MeshBuffer.hpp"
#include "math/CCMath.h"
#include "../../renderer/Effect.h"
#include "RenderDataList.hpp"
#include "../../renderer/EffectVariant.hpp"
namespace se {
class Object;
class HandleObject;
}
RENDERER_BEGIN
class NodeProxy;
class ModelBatcher;
/**
* @addtogroup scene
* @{
*/
class Assembler : public AssemblerBase
{
public:
class IARenderData {
public:
IARenderData();
IARenderData(const IARenderData& o);
~IARenderData();
void setEffect(EffectVariant* effect);
EffectVariant* getEffect() const;
private:
EffectVariant* _effect = nullptr;
public:
int meshIndex = -1;
int verticesStart = 0;
int verticesCount = -1;
int indicesStart = 0;
int indicesCount = -1;
};
Assembler();
virtual ~Assembler();
/*
* @brief Commit the current render handle to ModelBatcher
*/
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
/*
* @brief Do nothing
*/
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override {}
/*
* @brief before fill buffers handle
*/
virtual void beforeFillBuffers(std::size_t index) {}
/*
* @brief Fills render data in given index to the MeshBuffer
* @param[in] buffer The shared mesh buffer
* @param[in] index The index of render data to be updated
* @param[in] node
*/
virtual void fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index);
/**
* @brief Sets IArenderDataList
*/
virtual void setRenderDataList(RenderDataList* datas);
/**
* @brief Gets the vertex format.
*/
VertexFormat* getVertexFormat() const { return _vfmt; };
/**
* @brief Sets the vertex format.
*/
virtual void setVertexFormat(VertexFormat* vfmt);
/*
* @brief Update local render buffer opacity
* @param[in] index The index of render data to be updated
* @param[in] opacity Inherit opacity
*/
virtual void updateOpacity(std::size_t index, uint8_t opacity);
/**
* @brief ignore opacity flag, it will always not update vertices opacity
*/
void ignoreOpacityFlag() { _ignoreOpacityFlag = true; }
/**
* @brief Is ignore opacity.
* @return _ignoreOpacityFlag
*/
bool isIgnoreOpacityFlag() { return _ignoreOpacityFlag; }
/**
* @brief Enable ignore world matrix.
*/
void ignoreWorldMatrix() { _ignoreWorldMatrix = true; }
/**
* @brief Is ignore world matrix.
* @return _opacityAlwaysDirty
*/
bool isIgnoreWorldMatrix() { return _ignoreWorldMatrix; }
/**
* @brief Updates mesh index
*/
void updateMeshIndex(std::size_t iaIndex, int meshIndex);
/**
* @brief Updates indices range
*/
void updateIndicesRange(std::size_t iaIndex, int start, int count);
/**
* @brief Updates vertices range
*/
void updateVerticesRange(std::size_t iaIndex, int start, int count);
/**
* @brief Update the material for the given index.
* @param[in] iaIndex Render data index.
* @param[in] effect Effect pointer.
*/
virtual void updateEffect(std::size_t iaIndex, EffectVariant* effect);
/**
* @brief Resets ia data.
*/
virtual void reset() override;
/**
* @brief Gets the material for the given index.
* @param[in] index Render data index.
* @return Effect pointer.
*/
inline EffectVariant* getEffect(std::size_t index) const
{
if (index >= _iaDatas.size())
{
return nullptr;
}
return _iaDatas[index].getEffect();
}
/**
* @brief Gets Effect count.
* @return Count.
*/
inline std::size_t getIACount() const
{
return _iaDatas.size();
}
protected:
RenderDataList* _datas = nullptr;
std::vector<IARenderData> _iaDatas;
uint32_t _bytesPerVertex = 0;
size_t _posOffset = 0;
size_t _alphaOffset = 0;
VertexFormat* _vfmt = nullptr;
const VertexFormat::Element* _vfPos = nullptr;
const VertexFormat::Element* _vfColor = nullptr;
bool _ignoreWorldMatrix = false;
bool _ignoreOpacityFlag = false;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,69 @@
/****************************************************************************
Copyright (c) 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 "AssemblerBase.hpp"
RENDERER_BEGIN
AssemblerBase::AssemblerBase()
{
}
AssemblerBase::~AssemblerBase()
{
if (_jsDirty)
{
_jsDirty->unroot();
_jsDirty->decRef();
_jsDirty = nullptr;
}
_dirty = nullptr;
_dirtyLen = 0;
clearCustomWorldMatirx();
}
void AssemblerBase::setDirty(se_object_ptr jsDirty)
{
if (_jsDirty == jsDirty) return;
if (_jsDirty)
{
_jsDirty->unroot();
_jsDirty->decRef();
_jsDirty = nullptr;
}
if (jsDirty == nullptr) return;
_jsDirty = jsDirty;
_jsDirty->root();
_jsDirty->incRef();
_dirty = nullptr;
_dirtyLen = 0;
_jsDirty->getTypedArrayData((uint8_t**)&_dirty, &_dirtyLen);
}
RENDERER_END

View File

@@ -0,0 +1,180 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include <stdint.h>
#include "base/CCVector.h"
#include "../../renderer/Effect.h"
#include "scripting/js-bindings/jswrapper/Object.hpp"
#include "math/Mat4.h"
RENDERER_BEGIN
class NodeProxy;
class ModelBatcher;
class Scene;
/**
* @addtogroup scene
* @{
*/
/**
* @brief Base class for all assembler
* A assembler could take actions during node visit process, before and after all children visit.
*/
class AssemblerBase: public cocos2d::Ref
{
public:
enum AssemblerFlag {
VERTICES_OPACITY_CHANGED = 1 << 0,
VERTICES_DIRTY = 1 << 1,
};
AssemblerBase();
virtual ~AssemblerBase();
/**
* @brief Callback which will be invoked before visiting child nodes.
* @param[in] node The node being processed.
* @param[in] batcher
* @param[in] scene
*/
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) {}
/**
* @brief Callback which will be invoked after visiting child nodes.
* @param[in] node The node being processed.
* @param[in] batcher
* @param[in] scene
*/
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) {}
/**
* @brief Gets whether the current handle should use model matrix uniform during rendering
*/
bool getUseModel() const
{
return _useModel;
}
/**
* @brief Sets whether the current handle should use model matrix uniform during rendering
*/
void setUseModel(bool useModel)
{
_useModel = useModel;
}
/**
* @brief Gets custom world matrix
*/
const cocos2d::Mat4* getCustomWorldMatrix() const
{
return _worldMatrix;
}
/**
* @brief Sets custom world matrix
*/
void setCustomWorldMatrix(const cocos2d::Mat4& matrix)
{
if (!_worldMatrix)
{
_worldMatrix = new cocos2d::Mat4();
}
*_worldMatrix = matrix;
}
/**
* @brief Clear custom world matrix
*/
void clearCustomWorldMatirx()
{
if (_worldMatrix)
{
delete _worldMatrix;
_worldMatrix = nullptr;
}
}
/**
* @brief Sync script dirty flag.
*/
void setDirty(se_object_ptr jsDirty);
/**
* @brief Changes dirty flag.
*/
void enableDirty(uint32_t flag)
{
if (_dirty)
{
*_dirty |= flag;
}
}
/**
* @brief Changes dirty flag.
*/
void disableDirty(uint32_t flag)
{
if (_dirty)
{
*_dirty &= ~flag;
}
}
/**
* @brief Is flag dirty.
*/
bool isDirty(uint32_t flag)
{
if (_dirty)
{
return *_dirty & flag;
}
return false;
}
/**
* @brief Resets data.
*/
virtual void reset() {}
protected:
se::Object* _jsDirty = nullptr;
uint32_t* _dirty = nullptr;
std::size_t _dirtyLen = 0;
bool _useModel = false;
cocos2d::Mat4* _worldMatrix = nullptr;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,160 @@
/****************************************************************************
Copyright (c) 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 "AssemblerSprite.hpp"
#include "../RenderFlow.hpp"
RENDERER_BEGIN
AssemblerSprite::AssemblerSprite()
{
}
AssemblerSprite::~AssemblerSprite()
{
if(_localObj != nullptr)
{
_localObj->unroot();
_localObj->decRef();
_localObj = nullptr;
_localData = nullptr;
_localLen = 0;
}
}
void AssemblerSprite::setLocalData(se_object_ptr localData)
{
if (!localData || localData == _localObj) return;
if (_localObj)
{
_localObj->unroot();
_localObj->decRef();
}
_localObj = localData;
_localObj->root();
_localObj->incRef();
_localData = nullptr;
_localLen = 0;
_localObj->getTypedArrayData((uint8_t**)&_localData, (std::size_t*)&_localLen);
}
void AssemblerSprite::fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index)
{
if(!_datas || !_vfmt)
{
return;
}
if (index >= _iaDatas.size())
{
return;
}
MeshBuffer* buffer = batcher->getBuffer(_vfmt);
const IARenderData& ia = _iaDatas[index];
std::size_t meshIndex = ia.meshIndex >= 0 ? ia.meshIndex : index;
RenderData* data = _datas->getRenderData(meshIndex);
if (!data)
{
return;
}
CCASSERT(data->getVBytes() % _bytesPerVertex == 0, "AssemblerSprite::fillBuffers vertices data doesn't follow vertex format");
uint32_t vertexCount = ia.verticesCount >= 0 ? (uint32_t)ia.verticesCount : (uint32_t)data->getVBytes() / _bytesPerVertex;
uint32_t indexCount = ia.indicesCount >= 0 ? (uint32_t)ia.indicesCount : (uint32_t)data->getIBytes() / sizeof(unsigned short);
uint32_t vertexStart = (uint32_t)ia.verticesStart;
// must retrieve offset before request
auto& bufferOffset = buffer->request(vertexCount, indexCount);
uint32_t vBufferOffset = bufferOffset.vByte / sizeof(float);
uint32_t indexId = bufferOffset.index;
uint32_t vertexId = bufferOffset.vertex;
uint32_t vertexOffset = vertexId - vertexStart;
if (*_dirty & VERTICES_DIRTY || node->isDirty(RenderFlow::WORLD_TRANSFORM_CHANGED | RenderFlow::NODE_OPACITY_CHANGED))
{
generateWorldVertices();
calculateWorldVertices(node->getWorldMatrix());
}
float* dstWorldVerts = buffer->vData + vBufferOffset;
memcpy(dstWorldVerts, data->getVertices() + vertexStart * _bytesPerVertex, vertexCount * _bytesPerVertex);
// Copy index buffer with vertex offset
uint16_t* srcIndices = (uint16_t*)data->getIndices();
uint16_t* dstIndices = buffer->iData;
for (auto i = 0, j = ia.indicesStart; i < indexCount; ++i, ++j)
{
dstIndices[indexId++] = vertexOffset + srcIndices[j];
}
}
void AssemblerSprite::calculateWorldVertices(const Mat4& worldMat)
{
if(!_datas || !_vfmt)
{
return;
}
uint32_t num = _vfPos->num;
size_t dataPerVertex = _bytesPerVertex / sizeof(float);
for (std::size_t iaIdx = 0, iaCount = _iaDatas.size(); iaIdx < iaCount; iaIdx++)
{
const IARenderData& ia = _iaDatas[iaIdx];
std::size_t meshIndex = ia.meshIndex >= 0 ? ia.meshIndex : iaIdx;
RenderData* data = _datas->getRenderData(meshIndex);
if (!data) continue;
uint32_t vertexCount = ia.verticesCount >= 0 ? (uint32_t)ia.verticesCount : (uint32_t)data->getVBytes() / _bytesPerVertex;
uint32_t vertexStart = (uint32_t)ia.verticesStart;
float* srcWorldVerts = (float*)(data->getVertices() + vertexStart * _bytesPerVertex) + _posOffset;
switch (num) {
case 3:
for (uint32_t i = 0; i < vertexCount; ++i)
{
((cocos2d::Vec3*)srcWorldVerts)->transformMat4(*((cocos2d::Vec3*)srcWorldVerts), worldMat);
srcWorldVerts += dataPerVertex;
}
break;
case 2:
for (uint32_t i = 0; i < vertexCount; ++i)
{
float z = srcWorldVerts[2];
srcWorldVerts[2] = 0;
worldMat.transformPoint((cocos2d::Vec3*)srcWorldVerts);
srcWorldVerts[2] = z;
srcWorldVerts += dataPerVertex;
}
break;
}
}
*_dirty &= ~VERTICES_DIRTY;
}
RENDERER_END

View File

@@ -0,0 +1,48 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include "scripting/js-bindings/jswrapper/Object.hpp"
#include "Assembler.hpp"
RENDERER_BEGIN
class AssemblerSprite: public Assembler
{
public:
AssemblerSprite();
virtual ~AssemblerSprite();
virtual void setLocalData(se_object_ptr localData);
virtual void fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index) override;
virtual void calculateWorldVertices(const Mat4& worldMat);
virtual void generateWorldVertices() {};
protected:
se::Object* _localObj = nullptr;
float* _localData = nullptr;
std::size_t _localLen = 0;
};
RENDERER_END

View File

@@ -0,0 +1,133 @@
/****************************************************************************
Copyright (c) 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 "CustomAssembler.hpp"
#include "../NodeProxy.hpp"
#include "../ModelBatcher.hpp"
#include "../../renderer/Scene.h"
RENDERER_BEGIN
CustomAssembler::CustomAssembler()
{
}
CustomAssembler::~CustomAssembler()
{
for (std::size_t i = 0, n = _iaPool.size(); i < n; i++)
{
auto ia = _iaPool[i];
delete ia;
}
_iaPool.clear();
}
void CustomAssembler::handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene)
{
batcher->commitIA(node, this, node->getCullingMask());
}
void CustomAssembler::reset()
{
_iaCount = 0;
for (auto it = _iaPool.begin(); it != _iaPool.end(); it++)
{
(*it)->clear();
}
}
void CustomAssembler::updateIARange(std::size_t index, int start, int count)
{
auto ia = adjustIA(index);
if (!ia) return;
ia->setCount(count);
ia->setStart(start);
}
void CustomAssembler::updateIABuffer(std::size_t index, VertexBuffer* vb, IndexBuffer* ib)
{
auto ia = adjustIA(index);
if (!ia) return;
ia->setVertexBuffer(vb);
ia->setIndexBuffer(ib);
}
InputAssembler* CustomAssembler::adjustIA(std::size_t index)
{
auto size = _iaPool.size();
InputAssembler* ia = nullptr;
if (index == size)
{
ia = new InputAssembler();
_iaPool.push_back(ia);
}
else if (index < size)
{
ia = _iaPool[index];
}
else
{
cocos2d::log("CustomAssembler:updateIA index:%zu is out of range", index);
return nullptr;
}
auto newIACount = index + 1;
if (_iaCount < newIACount)
{
_iaCount = newIACount;
}
return ia;
}
InputAssembler* CustomAssembler::getIA(std::size_t index) const
{
if (index >= _iaCount)
{
return nullptr;
}
return _iaPool[index];
}
void CustomAssembler::updateEffect(std::size_t index, EffectVariant* effect)
{
auto size = _effects.size();
if (index == size)
{
_effects.pushBack(effect);
return;
}
else if (index < size)
{
_effects.replace(index, effect);
return;
}
cocos2d::log("CustomAssembler:updateEffect index:%zu out of range", index);
}
RENDERER_END

View File

@@ -0,0 +1,134 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "AssemblerBase.hpp"
#include <vector>
#include "../../renderer/InputAssembler.h"
#include "../../renderer/EffectVariant.hpp"
RENDERER_BEGIN
/**
* @addtogroup scene
* @{
*/
/**
* @brief Custom render handle base class
* Render components that manages render buffer directly like spine, dragonBones should extend from this handle type.
*/
class CustomAssembler : public AssemblerBase
{
public:
CustomAssembler();
virtual ~CustomAssembler();
/**
* @brief Updates InputAssembler indices range
* @param[in] index InputAssembler index.
* @param[in] start Indices buffer start pos
* @param[in] count Indices count
*/
virtual void updateIARange(std::size_t index, int start, int count);
/**
* @brief Updates InputAssembler indices and vertices buffer
* @param[in] index InputAssembler index.
* @param[in] vb Vertices buffer pointer
* @param[in] ib Indices buffer pointer
*/
virtual void updateIABuffer(std::size_t index, cocos2d::renderer::VertexBuffer* vb, cocos2d::renderer::IndexBuffer* ib);
/**
* @brief Gets input assembler by index
* @param[in] index.
*/
InputAssembler* getIA(std::size_t index) const;
/**
* @brief Gets input assembler count.
* @return Count.
*/
virtual inline std::size_t getIACount() const
{
return _iaCount;
}
/**
* @brief Commit the current render handle to ModelBatcher
*/
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
/**
* @brief Do nothing
*/
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override {}
/**
* @brief Resets ia data.
*/
virtual void reset() override;
/**
* @brief Adjusts ia data.
*/
virtual InputAssembler* adjustIA(std::size_t index);
/**
* @brief Update the material for the given index.
* @param[in] index Render data index.
* @param[in] effect Effect pointer.
*/
virtual void updateEffect(std::size_t index, EffectVariant* effect);
/**
* @brief Gets the material for the given index.
* @param[in] index Render data index.
* @return Effect pointer.
*/
inline EffectVariant* getEffect(std::size_t index) const
{
if (index >= _effects.size())
{
return nullptr;
}
return _effects.at(index);
}
/**
* @brief Clears all effect.
* @return Count.
*/
virtual void clearEffect()
{
_effects.clear();
}
protected:
std::vector<cocos2d::renderer::InputAssembler*> _iaPool;
cocos2d::Vector<EffectVariant*> _effects;
std::size_t _iaCount = 0;
};
// end of scene group
/// @}
RENDERER_END

View File

@@ -0,0 +1,91 @@
/****************************************************************************
Copyright (c) 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 "MaskAssembler.hpp"
#include "../ModelBatcher.hpp"
#include "../StencilManager.hpp"
#include "../../Macro.h"
RENDERER_BEGIN
MaskAssembler::MaskAssembler()
{
}
MaskAssembler::~MaskAssembler()
{
CC_SAFE_RELEASE(_renderSubHandle);
CC_SAFE_RELEASE(_clearSubHandle);
}
void MaskAssembler::setRenderSubHandle(Assembler* renderSubHandle)
{
if (_renderSubHandle == renderSubHandle) return;
CC_SAFE_RELEASE(_renderSubHandle);
_renderSubHandle = renderSubHandle;
CC_SAFE_RETAIN(_renderSubHandle);
}
void MaskAssembler::setClearSubHandle(Assembler* clearSubHandle)
{
if (_clearSubHandle == clearSubHandle) return;
CC_SAFE_RELEASE(_clearSubHandle);
_clearSubHandle = clearSubHandle;
CC_SAFE_RETAIN(_clearSubHandle);
}
void MaskAssembler::handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene)
{
batcher->flush();
batcher->flushIA();
StencilManager* instance = StencilManager::getInstance();
instance->pushMask(_inverted);
instance->clear();
batcher->commit(node, _clearSubHandle, node->getCullingMask());
batcher->flush();
instance->enterLevel();
if (_imageStencil)
{
batcher->commit(node, this, node->getCullingMask());
}
else if (_renderSubHandle)
{
_renderSubHandle->handle(node, batcher, scene);
}
batcher->flush();
instance->enableMask();
}
void MaskAssembler::postHandle(NodeProxy *node, ModelBatcher *batcher, Scene *scene)
{
batcher->flush();
batcher->flushIA();
batcher->setCurrentEffect(getEffect(0));
StencilManager::getInstance()->exitMask();
}
RENDERER_END

View File

@@ -0,0 +1,62 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include <stdio.h>
#include "Assembler.hpp"
#include "../MeshBuffer.hpp"
#include "math/CCMath.h"
#include "SimpleSprite2D.hpp"
class ModelBatcher;
RENDERER_BEGIN
class MaskAssembler: public SimpleSprite2D
{
public:
MaskAssembler();
virtual ~MaskAssembler();
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
virtual void postHandle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
void setMaskInverted(bool inverted) { _inverted = inverted; };
bool getMaskInverted() { return _inverted; };
void setRenderSubHandle(Assembler* renderSubHandle);
void setClearSubHandle(Assembler* clearSubHandle);
void setImageStencil(bool isImageStencil) { _imageStencil = isImageStencil; };
protected:
bool _inverted = false;
bool _imageStencil = false;
private:
Assembler* _renderSubHandle = nullptr;
Assembler* _clearSubHandle = nullptr;
};
RENDERER_END

View File

@@ -0,0 +1,111 @@
/****************************************************************************
Copyright (c) 2019 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 "MeshAssembler.hpp"
#include "../ModelBatcher.hpp"
RENDERER_BEGIN
MeshAssembler::MeshAssembler()
{
_useModel = true;
}
MeshAssembler::~MeshAssembler()
{
RENDERER_SAFE_RELEASE(_renderNode);
}
void MeshAssembler::handle(NodeProxy *node, ModelBatcher *batcher, Scene *scene)
{
if (_renderNode != nullptr)
{
batcher->commitIA(_renderNode, this, node->getCullingMask());
}
else
{
batcher->commitIA(node, this, node->getCullingMask());
}
batcher->flushIA();
}
void MeshAssembler::setNode(NodeProxy* node)
{
if (_renderNode == node)
{
return;
}
if (_renderNode != nullptr)
{
_renderNode->release();
}
_renderNode = node;
if (_renderNode != nullptr)
{
_renderNode->retain();
}
}
void MeshAssembler::updateIAData(std::size_t index, VertexFormat* vfmt, se_object_ptr vertices, se_object_ptr indices)
{
_datas.updateMesh(index, vertices, indices);
auto data = _datas.getRenderData(index);
auto ia = adjustIA(index);
auto ib = ia->getIndexBuffer();
if (!ib) {
ib = new IndexBuffer();
ib->autorelease();
ib->init(DeviceGraphics::getInstance(), IndexFormat::UINT16, Usage::STATIC, data->getIndices(), data->getIBytes(), (uint32_t)data->getIBytes() / sizeof(unsigned short));
ia->setIndexBuffer(ib);
}
else {
ib->update(0, data->getIndices(), data->getIBytes());
}
auto vb = ia->getVertexBuffer();
if (!vb) {
vb = new VertexBuffer();
vb->autorelease();
vb->init(DeviceGraphics::getInstance(), vfmt, Usage::STATIC, data->getVertices(), data->getVBytes(), (uint32_t)data->getVBytes() / vfmt->getBytes());
ia->setVertexBuffer(vb);
}
else {
vb->update(0, data->getVertices(), data->getVBytes());
}
ia->setCount(ib->getCount());
}
void MeshAssembler::reset()
{
CustomAssembler::reset();
_datas.clear();
}
RENDERER_END

View File

@@ -0,0 +1,54 @@
/****************************************************************************
Copyright (c) 2019 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include "CustomAssembler.hpp"
#include "../NodeProxy.hpp"
#include "../../gfx/VertexFormat.h"
#include "RenderDataList.hpp"
RENDERER_BEGIN
class MeshAssembler: public CustomAssembler
{
public:
MeshAssembler();
virtual ~MeshAssembler();
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
/**
* @brief Sets the related node proxy which provids model matrix for render.
*/
void setNode(NodeProxy* node);
void updateIAData(std::size_t index, VertexFormat* vfmt, se_object_ptr vertices, se_object_ptr indices);
virtual void reset() override;
protected:
NodeProxy* _renderNode = nullptr;
RenderDataList _datas;
};
RENDERER_END

View File

@@ -0,0 +1,136 @@
/****************************************************************************
Copyright (c) 2019 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 "Particle3DAssembler.hpp"
#include "../NodeProxy.hpp"
RENDERER_BEGIN
Particle3DAssembler::Particle3DAssembler()
{
}
Particle3DAssembler::~Particle3DAssembler()
{
CC_SAFE_RELEASE(_trailVfmt);
}
void Particle3DAssembler::setTrailVertexFormat(VertexFormat *vfmt)
{
if (_trailVfmt == vfmt) return;
CC_SAFE_RETAIN(vfmt);
CC_SAFE_RELEASE(_trailVfmt);
_trailVfmt = vfmt;
if (_trailVfmt)
{
_trailVertexBytes = _trailVfmt->getBytes();
const VertexFormat::Element* vfPos = _vfmt->getElement(ATTRIB_NAME_POSITION_HASH);
_trailPosOffset = vfPos->offset / 4;
}
}
void Particle3DAssembler::fillBuffer(NodeProxy *node, MeshBuffer *buffer, const IARenderData& ia, RenderData* data)
{
CCASSERT(data->getVBytes() % _bytesPerVertex == 0, "Assembler::fillBuffers vertices data doesn't follow vertex format");
uint32_t vertexCount = ia.verticesCount >= 0 ? (uint32_t)ia.verticesCount : (uint32_t)data->getVBytes() / _bytesPerVertex;
uint32_t indexCount = ia.indicesCount >= 0 ? (uint32_t)ia.indicesCount : (uint32_t)data->getIBytes() / sizeof(unsigned short);
uint32_t vertexStart = (uint32_t)ia.verticesStart;
// must retrieve offset before request
auto& bufferOffset = buffer->request(vertexCount, indexCount);
uint32_t vBufferOffset = bufferOffset.vByte / sizeof(float);
uint32_t indexId = bufferOffset.index;
uint32_t vertexId = bufferOffset.vertex;
uint32_t vertexOffset = vertexId - vertexStart;
float* worldVerts = buffer->vData + vBufferOffset;
memcpy(worldVerts, data->getVertices() + vertexStart * _bytesPerVertex, vertexCount * _bytesPerVertex);
// Copy index buffer with vertex offset
uint16_t* indices = (uint16_t*)data->getIndices();
uint16_t* dst = buffer->iData;
for (auto i = 0, j = ia.indicesStart; i < indexCount; ++i, ++j)
{
dst[indexId++] = vertexOffset + indices[j];
}
}
void Particle3DAssembler::fillTrailBuffer(NodeProxy *node, MeshBuffer *buffer, const IARenderData& ia, RenderData* data)
{
CCASSERT(data->getVBytes() % _trailVertexBytes == 0, "Assembler::fillBuffers vertices data doesn't follow vertex format");
uint32_t vertexCount = ia.verticesCount >= 0 ? (uint32_t)ia.verticesCount : (uint32_t)data->getVBytes() / _trailVertexBytes;
uint32_t indexCount = ia.indicesCount >= 0 ? (uint32_t)ia.indicesCount : (uint32_t)data->getIBytes() / sizeof(unsigned short);
uint32_t vertexStart = (uint32_t)ia.verticesStart;
// must retrieve offset before request
auto& bufferOffset = buffer->request(vertexCount, indexCount);
uint32_t vBufferOffset = bufferOffset.vByte / sizeof(float);
uint32_t indexId = bufferOffset.index;
uint32_t vertexId = bufferOffset.vertex;
uint32_t vertexOffset = vertexId - vertexStart;
float* worldVerts = buffer->vData + vBufferOffset;
memcpy(worldVerts, data->getVertices() + vertexStart * _trailVertexBytes, vertexCount * _trailVertexBytes);
// Copy index buffer with vertex offset
uint16_t* indices = (uint16_t*)data->getIndices();
uint16_t* dst = buffer->iData;
for (auto i = 0, j = ia.indicesStart; i < indexCount; ++i, ++j)
{
dst[indexId++] = vertexOffset + indices[j];
}
}
void Particle3DAssembler::fillBuffers(NodeProxy *node, ModelBatcher *batcher, std::size_t index)
{
VertexFormat* vfmt = index == 0 ? _vfmt : _trailVfmt;
if (!_datas || !vfmt)
{
return;
}
MeshBuffer* buffer = batcher->getBuffer(vfmt);
const IARenderData& ia = _iaDatas[index];
std::size_t meshIndex = ia.meshIndex >= 0 ? ia.meshIndex : index;
RenderData* data = _datas->getRenderData(meshIndex);
if (!data)
{
return;
}
if (index != 0)
{
fillTrailBuffer(node, buffer, ia, data);
}
else
{
fillBuffer(node, buffer, ia, data);
}
}
RENDERER_END

View File

@@ -0,0 +1,69 @@
/****************************************************************************
Copyright (c) 2019 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.
****************************************************************************/
#pragma once
#include "Assembler.hpp"
#include "../ModelBatcher.hpp"
RENDERER_BEGIN
class NodeProxy;
class ModelBatcher;
enum class Space: uint8_t
{
WORLD = 0,
LOCAL = 1,
CUSTOM = 2
};
class Particle3DAssembler: public Assembler
{
public:
Particle3DAssembler();
~Particle3DAssembler();
virtual void fillBuffers(NodeProxy *node, ModelBatcher *batcher, std::size_t index) override;
void setTrailVertexFormat(VertexFormat* vfmt);
void setTrailModuleEnable(bool enable) {_trailModuleEnable = enable;};
void setParticleSpace(Space space) {_particleSpace = space;};
void setTrailSpace(Space space) {_trailSpace = space;};
private:
void fillBuffer(NodeProxy *node, MeshBuffer *buffer, const IARenderData& ia, RenderData* data);
void fillTrailBuffer(NodeProxy *node, MeshBuffer *buffer, const IARenderData& ia, RenderData* data);
private:
Space _particleSpace = Space::LOCAL;
Space _trailSpace = Space::LOCAL;
uint32_t _trailVertexBytes = 0;
size_t _trailPosOffset = 0;
bool _trailModuleEnable = false;
VertexFormat* _trailVfmt = nullptr;
};
RENDERER_END

View File

@@ -0,0 +1,126 @@
/****************************************************************************
Copyright (c) 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 "RenderData.hpp"
#include "../../renderer/Effect.h"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
RENDERER_BEGIN
RenderData::RenderData ()
{
}
RenderData::RenderData (const RenderData& o)
{
setVertices(o._jsVertices);
setIndices(o._jsIndices);
}
RenderData::~RenderData ()
{
if(_jsVertices != nullptr)
{
_jsVertices->unroot();
_jsVertices->decRef();
_jsVertices = nullptr;
_vertices = nullptr;
_vBytes = 0;
}
if(_jsIndices != nullptr)
{
_jsIndices->unroot();
_jsIndices->decRef();
_jsIndices = nullptr;
_indices = nullptr;
_iBytes = 0;
}
}
void RenderData::setVertices (se::Object* jsVertices)
{
if (!jsVertices || jsVertices == _jsVertices) return;
if (_jsVertices)
{
_jsVertices->unroot();
_jsVertices->decRef();
}
_jsVertices = jsVertices;
_jsVertices->root();
_jsVertices->incRef();
_vertices = nullptr;
_vBytes = 0;
_jsVertices->getTypedArrayData(&_vertices, (std::size_t*)&_vBytes);
}
void RenderData::setIndices (se::Object* jsIndices)
{
if (!jsIndices || jsIndices == _jsIndices) return;
if (_jsIndices)
{
_jsIndices->unroot();
_jsIndices->decRef();
}
_jsIndices = jsIndices;
_jsIndices->root();
_jsIndices->incRef();
_indices = nullptr;
_iBytes = 0;
_jsIndices->getTypedArrayData(&_indices, (std::size_t*)&_iBytes);
}
uint8_t* RenderData::getVertices () const
{
return _vertices;
}
uint8_t* RenderData::getIndices () const
{
return _indices;
}
void RenderData::clear()
{
if(_jsVertices != nullptr)
{
_jsVertices->unroot();
_jsVertices->decRef();
_jsVertices = nullptr;
}
if(_jsIndices != nullptr)
{
_jsIndices->unroot();
_jsIndices->decRef();
_jsIndices = nullptr;
}
_vBytes = 0;
_iBytes = 0;
_vertices = nullptr;
_indices = nullptr;
}
RENDERER_END

View File

@@ -0,0 +1,66 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "../../Macro.h"
#include "base/CCRef.h"
#include <stdint.h>
namespace se {
class Object;
class HandleObject;
}
RENDERER_BEGIN
class Effect;
class RenderData {
public:
RenderData ();
RenderData (const RenderData& o);
virtual ~RenderData ();
void setVertices (se::Object* jsVertices);
void setIndices (se::Object* jsIndices);
uint8_t* getVertices () const;
uint8_t* getIndices () const;
unsigned long getVBytes () { return _vBytes; }
unsigned long getIBytes () { return _iBytes; }
void clear();
private:
unsigned long _vBytes = 0;
unsigned long _iBytes = 0;
uint8_t* _vertices = nullptr;
uint8_t* _indices = nullptr;
se::Object* _jsVertices = nullptr;
se::Object* _jsIndices = nullptr;
};
RENDERER_END

View File

@@ -0,0 +1,63 @@
/****************************************************************************
Copyright (c) 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 "RenderDataList.hpp"
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
RENDERER_BEGIN
void RenderDataList::updateMesh(std::size_t index, se_object_ptr vertices, se_object_ptr indices)
{
if (index >= _datas.size())
{
_datas.resize(index + 1);
}
se::ScriptEngine::getInstance()->clearException();
se::AutoHandleScope hs;
RenderData& data = _datas[index];
data.setVertices(vertices);
data.setIndices(indices);
}
RenderData* RenderDataList::getRenderData(std::size_t index)
{
if (index >= _datas.size())
{
return nullptr;
}
return &_datas[index];
}
void RenderDataList::clear()
{
for (auto it = _datas.begin(); it != _datas.end(); it++)
{
it->clear();
}
_datas.clear();
}
RENDERER_END

View File

@@ -0,0 +1,68 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "base/CCRef.h"
#include <vector>
#include "RenderData.hpp"
#include "scripting/js-bindings/jswrapper/Object.hpp"
namespace se {
class Object;
class HandleObject;
}
RENDERER_BEGIN
class RenderDataList: public cocos2d::Ref {
public:
RenderDataList () {}
virtual ~RenderDataList() {}
/**
* @brief Update the mesh data for the given index.
* @param[in] index Render data index.
* @param[in] vertices Vertex data.
* @param[in] indices Index data.
*/
void updateMesh(std::size_t index, se_object_ptr vertices, se_object_ptr indices);
/**
* @brief Gets the count of render datas
* @return Count.
*/
std::size_t getMeshCount() const { return _datas.size(); };
/**
* @brief Gets IARenderData.
* @return IARenderData.
*/
RenderData* getRenderData(std::size_t index);
/**
* @brief Resets all IARenderData.
*/
void clear();
private:
std::vector<RenderData> _datas;
};
RENDERER_END

View File

@@ -0,0 +1,105 @@
/****************************************************************************
Copyright (c) 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 "SimpleSprite2D.hpp"
#include "../RenderFlow.hpp"
RENDERER_BEGIN
SimpleSprite2D::SimpleSprite2D()
{
}
SimpleSprite2D::~SimpleSprite2D()
{
}
void SimpleSprite2D::fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index)
{
RenderData* data = _datas->getRenderData(0);
if (!data)
{
return;
}
MeshBuffer* buffer = batcher->getBuffer(_vfmt);
// must retrieve offset before request
auto& bufferOffset = buffer->request(4, 6);
uint32_t vBufferOffset = bufferOffset.vByte / sizeof(float);
uint32_t indexId = bufferOffset.index;
uint32_t vertexId = bufferOffset.vertex;
if (*_dirty & VERTICES_DIRTY || node->isDirty(RenderFlow::WORLD_TRANSFORM_CHANGED | RenderFlow::NODE_OPACITY_CHANGED))
{
float vl = _localData[0],
vr = _localData[2],
vb = _localData[1],
vt = _localData[3];
const Mat4& worldMat = node->getWorldMatrix();
size_t dataPerVertex = _bytesPerVertex / sizeof(float);
float* srcWorldVerts = (float*)data->getVertices();
// left bottom
float u = srcWorldVerts[2];
worldMat.transformVector(vl, vb, 0.0f, 1.0f, (cocos2d::Vec3*)srcWorldVerts);
srcWorldVerts[2] = u;
// right bottom
srcWorldVerts += dataPerVertex;
u = srcWorldVerts[2];
worldMat.transformVector(vr, vb, 0.0f, 1.0f, (cocos2d::Vec3*)srcWorldVerts);
srcWorldVerts[2] = u;
// left top
srcWorldVerts += dataPerVertex;
u = srcWorldVerts[2];
worldMat.transformVector(vl, vt, 0.0f, 1.0f, (cocos2d::Vec3*)srcWorldVerts);
srcWorldVerts[2] = u;
// right top
srcWorldVerts += dataPerVertex;
u = srcWorldVerts[2];
worldMat.transformVector(vr, vt, 0.0f, 1.0f, (cocos2d::Vec3*)srcWorldVerts);
srcWorldVerts[2] = u;
*_dirty &= ~VERTICES_DIRTY;
}
float* dstWorldVerts = buffer->vData + vBufferOffset;
memcpy(dstWorldVerts, data->getVertices(), 4 * _bytesPerVertex);
// Copy index buffer with vertex offset
uint16_t* srcIndices = (uint16_t*)data->getIndices();
uint16_t* dstIndices = buffer->iData;
for (auto i = 0, j = 0; i < 6; ++i, ++j)
{
dstIndices[indexId++] = vertexId + srcIndices[j];
}
}
RENDERER_END

View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "AssemblerSprite.hpp"
RENDERER_BEGIN
class SimpleSprite2D: public AssemblerSprite
{
public:
SimpleSprite2D();
virtual ~SimpleSprite2D();
virtual void fillBuffers(NodeProxy* node, ModelBatcher* batcher, std::size_t index) override;
};
RENDERER_END

View File

@@ -0,0 +1,80 @@
/****************************************************************************
Copyright (c) 2019 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 "SimpleSprite3D.hpp"
RENDERER_BEGIN
SimpleSprite3D::SimpleSprite3D()
{
}
SimpleSprite3D::~SimpleSprite3D()
{
}
void SimpleSprite3D::generateWorldVertices()
{
RenderData* data = _datas->getRenderData(0);
float* verts = (float*)data->getVertices();
auto floatsPerVert = _bytesPerVertex / sizeof(float);
std::size_t dstOffset = 0;
float vl = _localData[0],
vr = _localData[2],
vb = _localData[1],
vt = _localData[3];
// left bottom
verts[dstOffset] = vl;
verts[dstOffset+1] = vb;
verts[dstOffset+2] = 0;
dstOffset += floatsPerVert;
// right bottom
verts[dstOffset] = vr;
verts[dstOffset+1] = vb;
verts[dstOffset+2] = 0;
dstOffset += floatsPerVert;
// left top
verts[dstOffset] = vl;
verts[dstOffset+1] = vt;
verts[dstOffset+2] = 0;
dstOffset += floatsPerVert;
// right top
verts[dstOffset] = vr;
verts[dstOffset+1] = vt;
verts[dstOffset+2] = 0;
}
RENDERER_END

View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright (c) 2019 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.
****************************************************************************/
#pragma once
#include "AssemblerSprite.hpp"
RENDERER_BEGIN
class SimpleSprite3D : public AssemblerSprite
{
public:
SimpleSprite3D();
virtual ~SimpleSprite3D() override;
virtual void generateWorldVertices() override;
};
RENDERER_END

View File

@@ -0,0 +1,57 @@
/****************************************************************************
Copyright (c) 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 "SlicedSprite2D.hpp"
#include "../RenderFlow.hpp"
RENDERER_BEGIN
SlicedSprite2D::SlicedSprite2D()
{
}
SlicedSprite2D::~SlicedSprite2D()
{
}
void SlicedSprite2D::generateWorldVertices()
{
RenderData* data = _datas->getRenderData(0);
float* verts = (float*)data->getVertices();
auto floatsPerVert = _bytesPerVertex / sizeof(float);
for (auto row = 0; row < 4; ++row) {
float localRowY = _localData[row * 2 + 1];
for (auto col = 0; col < 4; ++col) {
float localColX = _localData[col * 2];
std::size_t worldIndex = (row * 4 + col) * floatsPerVert;
verts[worldIndex] = localColX ;
verts[worldIndex + 1] = localRowY;
}
}
}
RENDERER_END

View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "AssemblerSprite.hpp"
RENDERER_BEGIN
class SlicedSprite2D: public AssemblerSprite
{
public:
SlicedSprite2D();
virtual ~SlicedSprite2D();
virtual void generateWorldVertices() override;
};
RENDERER_END

View File

@@ -0,0 +1,57 @@
/****************************************************************************
Copyright (c) 2019 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 "SlicedSprite3D.hpp"
RENDERER_BEGIN
SlicedSprite3D::SlicedSprite3D()
{
};
SlicedSprite3D::~SlicedSprite3D()
{
};
void SlicedSprite3D::generateWorldVertices()
{
RenderData* data = _datas->getRenderData(0);
float* verts = (float*)data->getVertices();
auto floatsPerVert = _bytesPerVertex / sizeof(float);
for (auto row = 0; row < 4; ++row) {
float localRowY = _localData[row * 2 + 1];
for (auto col = 0; col < 4; ++col) {
float localColX = _localData[col * 2];
std::size_t worldIndex = (row * 4 + col) * floatsPerVert;
verts[worldIndex] = localColX ;
verts[worldIndex + 1] = localRowY;
verts[worldIndex + 2] = 0;
}
}
};
RENDERER_END

View File

@@ -0,0 +1,39 @@
/****************************************************************************
Copyright (c) 2019 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.
****************************************************************************/
#pragma once
#include "AssemblerSprite.hpp"
RENDERER_BEGIN
class SlicedSprite3D : public AssemblerSprite
{
public:
SlicedSprite3D();
virtual ~SlicedSprite3D() override;
virtual void generateWorldVertices() override;
};
RENDERER_END

View File

@@ -0,0 +1,98 @@
/****************************************************************************
Copyright (c) 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 "TiledMapAssembler.hpp"
#include "../NodeProxy.hpp"
#include "../ModelBatcher.hpp"
#include "../RenderFlow.hpp"
RENDERER_BEGIN
TiledMapAssembler::TiledMapAssembler()
{
}
TiledMapAssembler::~TiledMapAssembler()
{
}
void TiledMapAssembler::updateNodes(std::size_t iaIndex, const std::vector<std::string>& nodes)
{
_nodesMap[iaIndex] = nodes;
}
void TiledMapAssembler::clearNodes(std::size_t iaIndex)
{
_nodesMap.erase(iaIndex);
}
void TiledMapAssembler::handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene)
{
_node = node;
_batcher = batcher;
// Last tiles data may be empty, but has user node, so render it by manual.
auto lastNodesIndex = getIACount();
auto it = _nodesMap.find(lastNodesIndex);
if (it != _nodesMap.end())
{
renderNodes(lastNodesIndex);
}
Assembler::handle(node, batcher, scene);
}
void TiledMapAssembler::renderNodes(std::size_t index)
{
static cocos2d::Mat4 tempWorldMat;
const auto& worldMat = _node->getWorldMatrix();
auto it = _nodesMap.find(index);
if (it != _nodesMap.end())
{
auto flow = _batcher->getFlow();
for (auto& id : it->second) {
auto child = _node->getChildByID(id);
if (child)
{
child->enableVisit(true);
child->enableUpdateWorldMatrix(false);
child->updateLocalMatrix();
auto& localMat = child->getLocalMatrix();
cocos2d::Mat4::multiply(worldMat, localMat, &tempWorldMat);
child->updateWorldMatrix(tempWorldMat);
flow->visit(child);
child->enableUpdateWorldMatrix(true);
child->enableVisit(false);
}
}
}
_batcher->changeCommitState(ModelBatcher::Common);
}
void TiledMapAssembler::beforeFillBuffers(std::size_t index)
{
renderNodes(index);
}
RENDERER_END

View File

@@ -0,0 +1,50 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "Assembler.hpp"
#include <vector>
#include <map>
#include <string>
RENDERER_BEGIN
class TiledMapAssembler : public Assembler {
public:
TiledMapAssembler();
virtual ~TiledMapAssembler();
virtual void handle(NodeProxy *node, ModelBatcher* batcher, Scene* scene) override;
virtual void beforeFillBuffers(std::size_t index) override;
void updateNodes(std::size_t iaIndex, const std::vector<std::string>& nodes);
void clearNodes(std::size_t iaIndex);
private:
void renderNodes(std::size_t index);
private:
std::map<std::size_t, std::vector<std::string>> _nodesMap;
NodeProxy* _node = nullptr;
ModelBatcher* _batcher = nullptr;
};
RENDERER_END

View File

@@ -0,0 +1,43 @@
/****************************************************************************
Copyright (c) 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.
****************************************************************************/
#pragma once
#include "MemPool.hpp"
#include "NodeMemPool.hpp"
#include "NodeProxy.hpp"
#include "ModelBatcher.hpp"
#include "RenderFlow.hpp"
#include "MeshBuffer.hpp"
#include "assembler/Assembler.hpp"
#include "assembler/MaskAssembler.hpp"
#include "assembler/TiledMapAssembler.hpp"
#include "assembler/AssemblerSprite.hpp"
#include "assembler/SimpleSprite2D.hpp"
#include "assembler/SlicedSprite2D.hpp"
#include "assembler/MeshAssembler.hpp"
#include "assembler/SimpleSprite3D.hpp"
#include "assembler/SlicedSprite3D.hpp"
#include "assembler/Particle3DAssembler.hpp"