mirror of https://github.com/axmolengine/axmol.git
Remove Transparent Queue, Move transform calculation of Billboard to visit
This commit is contained in:
parent
7741daf091
commit
fee8bc1b28
|
@ -96,42 +96,102 @@ BillBoard* BillBoard::create(Mode mode)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
||||
void BillBoard::visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags)
|
||||
{
|
||||
// quick return if not visible. children won't be drawn.
|
||||
if (!_visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t flags = processParentFlags(parentTransform, parentFlags);
|
||||
|
||||
//Update Billboard transform
|
||||
calculateBillbaordTransform();
|
||||
|
||||
Director* director = Director::getInstance();
|
||||
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
|
||||
|
||||
bool visibleByCamera = isVisitableByVisitingCamera();
|
||||
|
||||
int i = 0;
|
||||
|
||||
if(!_children.empty())
|
||||
{
|
||||
sortAllChildren();
|
||||
// draw children zOrder < 0
|
||||
for( ; i < _children.size(); i++ )
|
||||
{
|
||||
auto node = _children.at(i);
|
||||
|
||||
if (node && node->getLocalZOrder() < 0)
|
||||
node->visit(renderer, _billboardTransform, flags);
|
||||
else
|
||||
break;
|
||||
}
|
||||
// self draw
|
||||
if (visibleByCamera)
|
||||
this->draw(renderer, _billboardTransform, flags);
|
||||
|
||||
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
|
||||
(*it)->visit(renderer, _billboardTransform, flags);
|
||||
}
|
||||
else if (visibleByCamera)
|
||||
{
|
||||
this->draw(renderer, _billboardTransform, flags);
|
||||
}
|
||||
|
||||
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
|
||||
}
|
||||
|
||||
void BillBoard::calculateBillbaordTransform()
|
||||
{
|
||||
//Get camera world position
|
||||
auto camera = Camera::getVisitingCamera();
|
||||
const Mat4& camWorldMat = camera->getNodeToWorldTransform();
|
||||
if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || memcmp(_mvTransform.m, transform.m, sizeof(float) * 16) != 0 || _modeDirty)
|
||||
|
||||
//TODO: use math lib to calculate math lib
|
||||
//Make it easier to read
|
||||
if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || _transformDirty || _modeDirty)
|
||||
{
|
||||
//Rotate based on anchor point
|
||||
Vec3 anchorPoint(_anchorPointInPoints.x , _anchorPointInPoints.y , 0.0f);
|
||||
Mat4 localToWorld = transform;
|
||||
Mat4 localToWorld = _modelViewTransform;
|
||||
localToWorld.translate(anchorPoint);
|
||||
|
||||
//Decide billboard mode
|
||||
Vec3 camDir;
|
||||
switch (_mode)
|
||||
{
|
||||
case Mode::VIEW_POINT_ORIENTED:
|
||||
camDir = Vec3(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
|
||||
break;
|
||||
case Mode::VIEW_PLANE_ORIENTED:
|
||||
camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
|
||||
break;
|
||||
default:
|
||||
case Mode::VIEW_POINT_ORIENTED:
|
||||
camDir = Vec3(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
|
||||
break;
|
||||
case Mode::VIEW_PLANE_ORIENTED:
|
||||
camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
|
||||
break;
|
||||
default:
|
||||
CCASSERT(false, "invalid billboard mode");
|
||||
break;
|
||||
break;
|
||||
}
|
||||
_modeDirty = false;
|
||||
|
||||
if (camDir.length() < MATH_TOLERANCE)
|
||||
{
|
||||
camDir.set(camWorldMat.m[8], camWorldMat.m[9], camWorldMat.m[10]);
|
||||
}
|
||||
camDir.normalize();
|
||||
|
||||
Quaternion rotationQuaternion;
|
||||
this->getNodeToWorldTransform().getRotation(&rotationQuaternion);
|
||||
|
||||
// fetch the rotation angle of z
|
||||
float rotationZ = atan2(2*(rotationQuaternion.w*rotationQuaternion.z + rotationQuaternion.x*rotationQuaternion.y),
|
||||
(1 - 2* (rotationQuaternion.y*rotationQuaternion.y + rotationQuaternion.z *rotationQuaternion.z)));
|
||||
(1 - 2* (rotationQuaternion.y*rotationQuaternion.y + rotationQuaternion.z *rotationQuaternion.z)));
|
||||
Mat4 rotationMatrix;
|
||||
rotationMatrix.setIdentity();
|
||||
rotationMatrix.rotateZ(rotationZ);
|
||||
|
||||
Vec3 upAxis = Vec3(rotationMatrix.m[4],rotationMatrix.m[5],rotationMatrix.m[6]);
|
||||
Vec3 x, y;
|
||||
camWorldMat.transformVector(upAxis, &y);
|
||||
|
@ -139,23 +199,26 @@ void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
|||
x.normalize();
|
||||
Vec3::cross(x, camDir, &y);
|
||||
y.normalize();
|
||||
|
||||
|
||||
float xlen = sqrtf(localToWorld.m[0] * localToWorld.m[0] + localToWorld.m[1] * localToWorld.m[1] + localToWorld.m[2] * localToWorld.m[2]);
|
||||
float ylen = sqrtf(localToWorld.m[4] * localToWorld.m[4] + localToWorld.m[5] * localToWorld.m[5] + localToWorld.m[6] * localToWorld.m[6]);
|
||||
float zlen = sqrtf(localToWorld.m[8] * localToWorld.m[8] + localToWorld.m[9] * localToWorld.m[9] + localToWorld.m[10] * localToWorld.m[10]);
|
||||
|
||||
|
||||
_billboardTransform.m[0] = x.x * xlen; _billboardTransform.m[1] = x.y * xlen; _billboardTransform.m[2] = x.z * xlen;
|
||||
_billboardTransform.m[4] = y.x * ylen; _billboardTransform.m[5] = y.y * ylen; _billboardTransform.m[6] = y.z * ylen;
|
||||
_billboardTransform.m[8] = -camDir.x * zlen; _billboardTransform.m[9] = -camDir.y * zlen; _billboardTransform.m[10] = -camDir.z * zlen;
|
||||
_billboardTransform.m[12] = localToWorld.m[12]; _billboardTransform.m[13] = localToWorld.m[13]; _billboardTransform.m[14] = localToWorld.m[14];
|
||||
|
||||
|
||||
_billboardTransform.translate(-anchorPoint);
|
||||
|
||||
const Mat4 &viewMat = camWorldMat.getInversed();
|
||||
_zDepthInView = -(viewMat.m[2] * _billboardTransform.m[12] + viewMat.m[6] * _billboardTransform.m[13] + viewMat.m[10] * _billboardTransform.m[14] + viewMat.m[14]);
|
||||
_mvTransform = transform;
|
||||
|
||||
_camWorldMat = camWorldMat;
|
||||
}
|
||||
}
|
||||
|
||||
void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
|
||||
{
|
||||
const Mat4 &viewMat = _camWorldMat.getInversed();
|
||||
_zDepthInView = -(viewMat.m[2] * _billboardTransform.m[12] + viewMat.m[6] * _billboardTransform.m[13] + viewMat.m[10] * _billboardTransform.m[14] + viewMat.m[14]);
|
||||
|
||||
//FIXME: frustum culling here
|
||||
{
|
||||
|
|
|
@ -88,6 +88,10 @@ public:
|
|||
Mode getMode() const;
|
||||
|
||||
//override
|
||||
|
||||
/** update billboard's transform and turn it towards camera */
|
||||
virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags);
|
||||
|
||||
/** draw BillBoard object */
|
||||
virtual void draw(Renderer *renderer, const Mat4 &transform, uint32_t flags) override;
|
||||
|
||||
|
@ -101,8 +105,9 @@ CC_CONSTRUCTOR_ACCESS:
|
|||
|
||||
protected:
|
||||
|
||||
void calculateBillbaordTransform();
|
||||
|
||||
Mat4 _camWorldMat;
|
||||
Mat4 _mvTransform;
|
||||
Mat4 _billboardTransform;
|
||||
|
||||
float _zDepthInView;
|
||||
|
|
|
@ -131,32 +131,6 @@ void RenderQueue::clear()
|
|||
_queuePosZ.clear();
|
||||
}
|
||||
|
||||
// helper
|
||||
static bool compareTransparentRenderCommand(RenderCommand* a, RenderCommand* b)
|
||||
{
|
||||
return a->getGlobalOrder() > b->getGlobalOrder();
|
||||
}
|
||||
|
||||
void TransparentRenderQueue::push_back(RenderCommand* command)
|
||||
{
|
||||
_queueCmd.push_back(command);
|
||||
}
|
||||
|
||||
void TransparentRenderQueue::sort()
|
||||
{
|
||||
std::sort(std::begin(_queueCmd), std::end(_queueCmd), compareTransparentRenderCommand);
|
||||
}
|
||||
|
||||
RenderCommand* TransparentRenderQueue::operator[](ssize_t index) const
|
||||
{
|
||||
return _queueCmd[index];
|
||||
}
|
||||
|
||||
void TransparentRenderQueue::clear()
|
||||
{
|
||||
_queueCmd.clear();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
@ -531,65 +505,6 @@ void Renderer::visitRenderQueue(const RenderQueue& queue)
|
|||
flush();
|
||||
}
|
||||
|
||||
void Renderer::visitTransparentRenderQueue(const TransparentRenderQueue& queue)
|
||||
{
|
||||
// do not batch for transparent objects
|
||||
ssize_t size = queue.size();
|
||||
|
||||
_batchedCommands.clear();
|
||||
_filledVertex = 0;
|
||||
_filledIndex = 0;
|
||||
|
||||
for (ssize_t index = 0; index < size; ++index)
|
||||
{
|
||||
auto command = queue[index];
|
||||
auto commandType = command->getType();
|
||||
if( RenderCommand::Type::TRIANGLES_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<TrianglesCommand*>(command);
|
||||
_batchedCommands.push_back(cmd);
|
||||
fillVerticesAndIndices(cmd);
|
||||
drawBatchedTriangles();
|
||||
}
|
||||
else if(RenderCommand::Type::QUAD_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<QuadCommand*>(command);
|
||||
_batchQuadCommands.push_back(cmd);
|
||||
fillQuads(cmd);
|
||||
drawBatchedQuads();
|
||||
}
|
||||
else if(RenderCommand::Type::GROUP_COMMAND == commandType)
|
||||
{
|
||||
int renderQueueID = (static_cast<GroupCommand*>(command))->getRenderQueueID();
|
||||
visitRenderQueue(_renderGroups[renderQueueID]);
|
||||
}
|
||||
else if(RenderCommand::Type::CUSTOM_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<CustomCommand*>(command);
|
||||
cmd->execute();
|
||||
}
|
||||
else if(RenderCommand::Type::BATCH_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<BatchCommand*>(command);
|
||||
cmd->execute();
|
||||
}
|
||||
else if(RenderCommand::Type::PRIMITIVE_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<PrimitiveCommand*>(command);
|
||||
cmd->execute();
|
||||
}
|
||||
else if (RenderCommand::Type::MESH_COMMAND == commandType)
|
||||
{
|
||||
auto cmd = static_cast<MeshCommand*>(command);
|
||||
cmd->execute();
|
||||
}
|
||||
else
|
||||
{
|
||||
CCLOGERROR("Unknown commands in renderQueue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::render()
|
||||
{
|
||||
//Uncomment this once everything is rendered by new renderer
|
||||
|
@ -607,16 +522,6 @@ void Renderer::render()
|
|||
renderqueue.sort();
|
||||
}
|
||||
visitRenderQueue(_renderGroups[0]);
|
||||
|
||||
//Process render commands
|
||||
//draw transparent objects here, do not batch for transparent objects
|
||||
if (0 < _transparentRenderGroups.size())
|
||||
{
|
||||
_transparentRenderGroups.sort();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
visitTransparentRenderQueue(_transparentRenderGroups);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
clean();
|
||||
_isRendering = false;
|
||||
|
@ -643,8 +548,6 @@ void Renderer::clean()
|
|||
_numberQuads = 0;
|
||||
_lastMaterialID = 0;
|
||||
_lastBatchedMeshCommand = nullptr;
|
||||
|
||||
_transparentRenderGroups.clear();
|
||||
}
|
||||
|
||||
void Renderer::clear()
|
||||
|
|
|
@ -65,22 +65,6 @@ protected:
|
|||
std::vector<RenderCommand*> _queuePosZ;
|
||||
};
|
||||
|
||||
//render queue for transparency object, NOTE that the _globalOrder of RenderCommand is the distance to the camera when added to the transparent queue
|
||||
class TransparentRenderQueue {
|
||||
public:
|
||||
void push_back(RenderCommand* command);
|
||||
ssize_t size() const
|
||||
{
|
||||
return _queueCmd.size();
|
||||
}
|
||||
void sort();
|
||||
RenderCommand* operator[](ssize_t index) const;
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
std::vector<RenderCommand*> _queueCmd;
|
||||
};
|
||||
|
||||
struct RenderStackElement
|
||||
{
|
||||
int renderQueueID;
|
||||
|
@ -172,8 +156,6 @@ protected:
|
|||
|
||||
void processRenderCommand(RenderCommand* command);
|
||||
void visitRenderQueue(const RenderQueue& queue);
|
||||
|
||||
void visitTransparentRenderQueue(const TransparentRenderQueue& queue);
|
||||
|
||||
void fillVerticesAndIndices(const TrianglesCommand* cmd);
|
||||
void fillQuads(const QuadCommand* cmd);
|
||||
|
@ -184,7 +166,6 @@ protected:
|
|||
std::stack<int> _commandGroupStack;
|
||||
|
||||
std::vector<RenderQueue> _renderGroups;
|
||||
TransparentRenderQueue _transparentRenderGroups; //transparency objects
|
||||
|
||||
uint32_t _lastMaterialID;
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ BillBoardTest::BillBoardTest()
|
|||
auto billboard = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]);
|
||||
billboard->setScale(0.5f);
|
||||
billboard->setPosition3D(Vec3(0.0f, 0.0f, CCRANDOM_MINUS1_1() * 150.0f));
|
||||
billboard->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
|
||||
billboard->setOpacity(CCRANDOM_0_1() * 128 + 128);
|
||||
_billboards.push_back(billboard);
|
||||
layer->addChild(billboard);
|
||||
|
@ -204,7 +203,6 @@ void BillBoardTest::addNewBillBoradWithCoords(Vec3 p)
|
|||
auto billborad = BillBoard::create(imgs[(unsigned int)(CCRANDOM_0_1() * 1 + 0.5)]);
|
||||
billborad->setScale(0.5f);
|
||||
billborad->setPosition3D(Vec3(p.x, p.y, -150.0f + 30 * i));
|
||||
billborad->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
|
||||
billborad->setOpacity(CCRANDOM_0_1() * 128 + 128);
|
||||
|
||||
_layerBillBorad->addChild(billborad);
|
||||
|
@ -233,7 +231,6 @@ void BillBoardTest::addNewAniBillBoradWithCoords(Vec3 p)
|
|||
|
||||
auto action = Animate::create(animation);
|
||||
billboardAni->runAction(RepeatForever::create(action));
|
||||
billboardAni->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
|
||||
billboardAni->setOpacity(CCRANDOM_0_1() * 128 + 128);
|
||||
_billboards.push_back(billboardAni);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue