Remove Transparent Queue, Move transform calculation of Billboard to visit

This commit is contained in:
Nite Luo 2015-01-12 18:17:47 -08:00
parent 7741daf091
commit fee8bc1b28
5 changed files with 88 additions and 139 deletions

View File

@ -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
{

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -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);
}