/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2006 Torus Knot Software Ltd Also see acknowledgements in Readme.html This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt. You may alternatively use this source under the terms of a specific version of the OGRE Unrestricted License provided you have obtained such a license from Torus Knot Software Ltd. ----------------------------------------------------------------------------- */ #include "OgreStableHeaders.h" #include "OgreBillboardParticleRenderer.h" #include "OgreParticle.h" #include "OgreStringConverter.h" namespace Ogre { String rendererTypeName = "billboard"; //----------------------------------------------------------------------- BillboardParticleRenderer::CmdBillboardType BillboardParticleRenderer::msBillboardTypeCmd; BillboardParticleRenderer::CmdBillboardOrigin BillboardParticleRenderer::msBillboardOriginCmd; BillboardParticleRenderer::CmdBillboardRotationType BillboardParticleRenderer::msBillboardRotationTypeCmd; BillboardParticleRenderer::CmdCommonDirection BillboardParticleRenderer::msCommonDirectionCmd; BillboardParticleRenderer::CmdCommonUpVector BillboardParticleRenderer::msCommonUpVectorCmd; BillboardParticleRenderer::CmdPointRendering BillboardParticleRenderer::msPointRenderingCmd; BillboardParticleRenderer::CmdAccurateFacing BillboardParticleRenderer::msAccurateFacingCmd; //----------------------------------------------------------------------- BillboardParticleRenderer::BillboardParticleRenderer() { if (createParamDictionary("BillboardParticleRenderer")) { ParamDictionary* dict = getParamDictionary(); dict->addParameter(ParameterDef("billboard_type", "The type of billboard to use. 'point' means a simulated spherical particle, " "'oriented_common' means all particles in the set are oriented around common_direction, " "'oriented_self' means particles are oriented around their own direction, " "'perpendicular_common' means all particles are perpendicular to common_direction, " "and 'perpendicular_self' means particles are perpendicular to their own direction.", PT_STRING), &msBillboardTypeCmd); dict->addParameter(ParameterDef("billboard_origin", "This setting controls the fine tuning of where a billboard appears in relation to it's position. " "Possible value are: 'top_left', 'top_center', 'top_right', 'center_left', 'center', 'center_right', " "'bottom_left', 'bottom_center' and 'bottom_right'. Default value is 'center'.", PT_STRING), &msBillboardOriginCmd); dict->addParameter(ParameterDef("billboard_rotation_type", "This setting controls the billboard rotation type. " "'vertex' means rotate the billboard's vertices around their facing direction." "'texcoord' means rotate the billboard's texture coordinates. Default value is 'texcoord'.", PT_STRING), &msBillboardRotationTypeCmd); dict->addParameter(ParameterDef("common_direction", "Only useful when billboard_type is oriented_common or perpendicular_common. " "When billboard_type is oriented_common, this parameter sets the common orientation for " "all particles in the set (e.g. raindrops may all be oriented downwards). " "When billboard_type is perpendicular_common, this parameter sets the perpendicular vector for " "all particles in the set (e.g. an aureola around the player and parallel to the ground).", PT_VECTOR3), &msCommonDirectionCmd); dict->addParameter(ParameterDef("common_up_vector", "Only useful when billboard_type is perpendicular_self or perpendicular_common. This " "parameter sets the common up-vector for all particles in the set (e.g. an aureola around " "the player and parallel to the ground).", PT_VECTOR3), &msCommonUpVectorCmd); dict->addParameter(ParameterDef("point_rendering", "Set whether or not particles will use point rendering " "rather than manually generated quads. This allows for faster " "rendering of point-oriented particles although introduces some " "limitations too such as requiring a common particle size." "Possible values are 'true' or 'false'.", PT_BOOL), &msPointRenderingCmd); dict->addParameter(ParameterDef("accurate_facing", "Set whether or not particles will be oriented to the camera " "based on the relative position to the camera rather than just " "the camera direction. This is more accurate but less optimal. " "Cannot be combined with point rendering.", PT_BOOL), &msAccurateFacingCmd); } // Create billboard set mBillboardSet = new BillboardSet("", 0, true); // World-relative axes mBillboardSet->setBillboardsInWorldSpace(true); } //----------------------------------------------------------------------- BillboardParticleRenderer::~BillboardParticleRenderer() { delete mBillboardSet; } //----------------------------------------------------------------------- const String& BillboardParticleRenderer::getType(void) const { return rendererTypeName; } //----------------------------------------------------------------------- void BillboardParticleRenderer::_updateRenderQueue(RenderQueue* queue, std::list& currentParticles, bool cullIndividually) { mBillboardSet->setCullIndividually(cullIndividually); // Update billboard set geometry mBillboardSet->beginBillboards(currentParticles.size()); Billboard bb; for (std::list::iterator i = currentParticles.begin(); i != currentParticles.end(); ++i) { Particle* p = *i; bb.mPosition = p->position; if (mBillboardSet->getBillboardType() == BBT_ORIENTED_SELF || mBillboardSet->getBillboardType() == BBT_PERPENDICULAR_SELF) { // Normalise direction vector bb.mDirection = p->direction; bb.mDirection.normalise(); } bb.mColour = p->colour; bb.mRotation = p->rotation; // Assign and compare at the same time if (bb.mOwnDimensions = p->mOwnDimensions) { bb.mWidth = p->mWidth; bb.mHeight = p->mHeight; } mBillboardSet->injectBillboard(bb); } mBillboardSet->endBillboards(); // Update the queue mBillboardSet->_updateRenderQueue(queue); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_setMaterial(MaterialPtr& mat) { mBillboardSet->setMaterialName(mat->getName()); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setBillboardType(BillboardType bbt) { mBillboardSet->setBillboardType(bbt); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setUseAccurateFacing(bool acc) { mBillboardSet->setUseAccurateFacing(acc); } //----------------------------------------------------------------------- bool BillboardParticleRenderer::getUseAccurateFacing(void) const { return mBillboardSet->getUseAccurateFacing(); } //----------------------------------------------------------------------- BillboardType BillboardParticleRenderer::getBillboardType(void) const { return mBillboardSet->getBillboardType(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setBillboardRotationType(BillboardRotationType rotationType) { mBillboardSet->setBillboardRotationType(rotationType); } //----------------------------------------------------------------------- BillboardRotationType BillboardParticleRenderer::getBillboardRotationType(void) const { return mBillboardSet->getBillboardRotationType(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setCommonDirection(const Vector3& vec) { mBillboardSet->setCommonDirection(vec); } //----------------------------------------------------------------------- const Vector3& BillboardParticleRenderer::getCommonDirection(void) const { return mBillboardSet->getCommonDirection(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setCommonUpVector(const Vector3& vec) { mBillboardSet->setCommonUpVector(vec); } //----------------------------------------------------------------------- const Vector3& BillboardParticleRenderer::getCommonUpVector(void) const { return mBillboardSet->getCommonUpVector(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyCurrentCamera(Camera* cam) { mBillboardSet->_notifyCurrentCamera(cam); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyParticleRotated(void) { mBillboardSet->_notifyBillboardRotated(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyDefaultDimensions(Real width, Real height) { mBillboardSet->setDefaultDimensions(width, height); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyParticleResized(void) { mBillboardSet->_notifyBillboardResized(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyParticleQuota(size_t quota) { mBillboardSet->setPoolSize(quota); } //----------------------------------------------------------------------- void BillboardParticleRenderer::_notifyAttached(Node* parent, bool isTagPoint) { mBillboardSet->_notifyAttached(parent, isTagPoint); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setRenderQueueGroup(uint8 queueID) { assert(queueID <= RENDER_QUEUE_MAX && "Render queue out of range!"); mBillboardSet->setRenderQueueGroup(queueID); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setKeepParticlesInLocalSpace(bool keepLocal) { mBillboardSet->setBillboardsInWorldSpace(!keepLocal); } //----------------------------------------------------------------------- SortMode BillboardParticleRenderer::_getSortMode(void) const { return mBillboardSet->_getSortMode(); } //----------------------------------------------------------------------- void BillboardParticleRenderer::setPointRenderingEnabled(bool enabled) { mBillboardSet->setPointRenderingEnabled(enabled); } //----------------------------------------------------------------------- bool BillboardParticleRenderer::isPointRenderingEnabled(void) const { return mBillboardSet->isPointRenderingEnabled(); } //----------------------------------------------------------------------- //----------------------------------------------------------------------- //----------------------------------------------------------------------- const String& BillboardParticleRendererFactory::getType() const { return rendererTypeName; } //----------------------------------------------------------------------- ParticleSystemRenderer* BillboardParticleRendererFactory::createInstance( const String& name ) { return new BillboardParticleRenderer(); } //----------------------------------------------------------------------- void BillboardParticleRendererFactory::destroyInstance( ParticleSystemRenderer* inst) { delete inst; } //----------------------------------------------------------------------- //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdBillboardType::doGet(const void* target) const { BillboardType t = static_cast(target)->getBillboardType(); switch(t) { case BBT_POINT: return "point"; break; case BBT_ORIENTED_COMMON: return "oriented_common"; break; case BBT_ORIENTED_SELF: return "oriented_self"; break; case BBT_PERPENDICULAR_COMMON: return "perpendicular_common"; case BBT_PERPENDICULAR_SELF: return "perpendicular_self"; } // Compiler nicety return ""; } void BillboardParticleRenderer::CmdBillboardType::doSet(void* target, const String& val) { BillboardType t; if (val == "point") { t = BBT_POINT; } else if (val == "oriented_common") { t = BBT_ORIENTED_COMMON; } else if (val == "oriented_self") { t = BBT_ORIENTED_SELF; } else if (val == "perpendicular_common") { t = BBT_PERPENDICULAR_COMMON; } else if (val == "perpendicular_self") { t = BBT_PERPENDICULAR_SELF; } else { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid billboard_type '" + val + "'", "ParticleSystem::CmdBillboardType::doSet"); } static_cast(target)->setBillboardType(t); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdBillboardOrigin::doGet(const void* target) const { BillboardOrigin o = static_cast(target)->getBillboardOrigin(); switch (o) { case BBO_TOP_LEFT: return "top_left"; case BBO_TOP_CENTER: return "top_center"; case BBO_TOP_RIGHT: return "top_right"; case BBO_CENTER_LEFT: return "center_left"; case BBO_CENTER: return "center"; case BBO_CENTER_RIGHT: return "center_right"; case BBO_BOTTOM_LEFT: return "bottom_left"; case BBO_BOTTOM_CENTER: return "bottom_center"; case BBO_BOTTOM_RIGHT: return "bottom_right"; } // Compiler nicety return StringUtil::BLANK; } void BillboardParticleRenderer::CmdBillboardOrigin::doSet(void* target, const String& val) { BillboardOrigin o; if (val == "top_left") o = BBO_TOP_LEFT; else if (val =="top_center") o = BBO_TOP_CENTER; else if (val =="top_right") o = BBO_TOP_RIGHT; else if (val =="center_left") o = BBO_CENTER_LEFT; else if (val =="center") o = BBO_CENTER; else if (val =="center_right") o = BBO_CENTER_RIGHT; else if (val =="bottom_left") o = BBO_BOTTOM_LEFT; else if (val =="bottom_center") o = BBO_BOTTOM_CENTER; else if (val =="bottom_right") o = BBO_BOTTOM_RIGHT; else { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid billboard_origin '" + val + "'", "ParticleSystem::CmdBillboardOrigin::doSet"); } static_cast(target)->setBillboardOrigin(o); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdBillboardRotationType::doGet(const void* target) const { BillboardRotationType r = static_cast(target)->getBillboardRotationType(); switch(r) { case BBR_VERTEX: return "vertex"; case BBR_TEXCOORD: return "texcoord"; } // Compiler nicety return StringUtil::BLANK; } void BillboardParticleRenderer::CmdBillboardRotationType::doSet(void* target, const String& val) { BillboardRotationType r; if (val == "vertex") r = BBR_VERTEX; else if (val == "texcoord") r = BBR_TEXCOORD; else { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid billboard_rotation_type '" + val + "'", "ParticleSystem::CmdBillboardRotationType::doSet"); } static_cast(target)->setBillboardRotationType(r); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdCommonDirection::doGet(const void* target) const { return StringConverter::toString( static_cast(target)->getCommonDirection() ); } void BillboardParticleRenderer::CmdCommonDirection::doSet(void* target, const String& val) { static_cast(target)->setCommonDirection( StringConverter::parseVector3(val)); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdCommonUpVector::doGet(const void* target) const { return StringConverter::toString( static_cast(target)->getCommonUpVector() ); } void BillboardParticleRenderer::CmdCommonUpVector::doSet(void* target, const String& val) { static_cast(target)->setCommonUpVector( StringConverter::parseVector3(val)); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdPointRendering::doGet(const void* target) const { return StringConverter::toString( static_cast(target)->isPointRenderingEnabled() ); } void BillboardParticleRenderer::CmdPointRendering::doSet(void* target, const String& val) { static_cast(target)->setPointRenderingEnabled( StringConverter::parseBool(val)); } //----------------------------------------------------------------------- String BillboardParticleRenderer::CmdAccurateFacing::doGet(const void* target) const { return StringConverter::toString( static_cast(target)->getUseAccurateFacing() ); } void BillboardParticleRenderer::CmdAccurateFacing::doSet(void* target, const String& val) { static_cast(target)->setUseAccurateFacing( StringConverter::parseBool(val)); } }