| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604 |
- /*
- -----------------------------------------------------------------------------
- This source file is part of OGRE
- (Object-oriented Graphics Rendering Engine)
- For the latest info, see http://www.ogre3d.org/
- Copyright (c) 2000-2011 Torus Knot Software Ltd
- 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 "CmHardwareVertexBuffer.h"
- #include "CmColor.h"
- #include "CmException.h"
- #include "CmHardwareBufferManager.h"
- #include "CmDefaultHardwareBufferManager.h"
- #include "CmRenderSystem.h"
- #include "CmRenderSystemManager.h"
- #include "CmVertexDeclarationRTTI.h"
- namespace CamelotEngine {
- //-----------------------------------------------------------------------------
- HardwareVertexBuffer::HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
- size_t numVertices, HardwareBuffer::Usage usage,
- bool useSystemMemory, bool useShadowBuffer)
- : HardwareBuffer(usage, useSystemMemory, useShadowBuffer),
- mMgr(mgr),
- mNumVertices(numVertices),
- mVertexSize(vertexSize)
- {
- // Calculate the size of the vertices
- mSizeInBytes = mVertexSize * numVertices;
- // Create a shadow buffer if required
- if (mUseShadowBuffer)
- {
- mpShadowBuffer = new DefaultHardwareVertexBuffer(mMgr, mVertexSize,
- mNumVertices, HardwareBuffer::HBU_DYNAMIC);
- }
- }
- //-----------------------------------------------------------------------------
- HardwareVertexBuffer::~HardwareVertexBuffer()
- {
- if (mMgr)
- {
- mMgr->_notifyVertexBufferDestroyed(this);
- }
- if (mpShadowBuffer)
- {
- delete mpShadowBuffer;
- }
- }
- //-----------------------------------------------------------------------------
- VertexElement::VertexElement(unsigned short source, size_t offset,
- VertexElementType theType, VertexElementSemantic semantic, unsigned short index)
- : mSource(source), mOffset(offset), mType(theType),
- mSemantic(semantic), mIndex(index)
- {
- }
- //-----------------------------------------------------------------------------
- size_t VertexElement::getSize(void) const
- {
- return getTypeSize(mType);
- }
- //-----------------------------------------------------------------------------
- size_t VertexElement::getTypeSize(VertexElementType etype)
- {
- switch(etype)
- {
- case VET_COLOUR:
- case VET_COLOUR_ABGR:
- case VET_COLOUR_ARGB:
- return sizeof(RGBA);
- case VET_FLOAT1:
- return sizeof(float);
- case VET_FLOAT2:
- return sizeof(float)*2;
- case VET_FLOAT3:
- return sizeof(float)*3;
- case VET_FLOAT4:
- return sizeof(float)*4;
- case VET_SHORT1:
- return sizeof(short);
- case VET_SHORT2:
- return sizeof(short)*2;
- case VET_SHORT3:
- return sizeof(short)*3;
- case VET_SHORT4:
- return sizeof(short)*4;
- case VET_UBYTE4:
- return sizeof(unsigned char)*4;
- }
- return 0;
- }
- //-----------------------------------------------------------------------------
- unsigned short VertexElement::getTypeCount(VertexElementType etype)
- {
- switch (etype)
- {
- case VET_COLOUR:
- case VET_COLOUR_ABGR:
- case VET_COLOUR_ARGB:
- return 1;
- case VET_FLOAT1:
- return 1;
- case VET_FLOAT2:
- return 2;
- case VET_FLOAT3:
- return 3;
- case VET_FLOAT4:
- return 4;
- case VET_SHORT1:
- return 1;
- case VET_SHORT2:
- return 2;
- case VET_SHORT3:
- return 3;
- case VET_SHORT4:
- return 4;
- case VET_UBYTE4:
- return 4;
- }
- CM_EXCEPT(InvalidParametersException, "Invalid type");
- }
- //-----------------------------------------------------------------------------
- VertexElementType VertexElement::multiplyTypeCount(VertexElementType baseType,
- unsigned short count)
- {
- switch (baseType)
- {
- case VET_FLOAT1:
- switch(count)
- {
- case 1:
- return VET_FLOAT1;
- case 2:
- return VET_FLOAT2;
- case 3:
- return VET_FLOAT3;
- case 4:
- return VET_FLOAT4;
- default:
- break;
- }
- break;
- case VET_SHORT1:
- switch(count)
- {
- case 1:
- return VET_SHORT1;
- case 2:
- return VET_SHORT2;
- case 3:
- return VET_SHORT3;
- case 4:
- return VET_SHORT4;
- default:
- break;
- }
- break;
- default:
- break;
- }
- CM_EXCEPT(InvalidParametersException, "Invalid base type");
- }
- //--------------------------------------------------------------------------
- VertexElementType VertexElement::getBestColourVertexElementType(void)
- {
- // Use the current render system to determine if possible
- if (CamelotEngine::RenderSystemManager::getActive())
- {
- return CamelotEngine::RenderSystemManager::getActive()->getColorVertexElementType();
- }
- else
- {
- // We can't know the specific type right now, so pick a type
- // based on platform
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- return VET_COLOUR_ARGB; // prefer D3D format on windows
- #else
- return VET_COLOUR_ABGR; // prefer GL format on everything else
- #endif
- }
- }
- //--------------------------------------------------------------------------
- void VertexElement::convertColourValue(VertexElementType srcType,
- VertexElementType dstType, UINT32* ptr)
- {
- if (srcType == dstType)
- return;
- // Conversion between ARGB and ABGR is always a case of flipping R/B
- *ptr =
- ((*ptr&0x00FF0000)>>16)|((*ptr&0x000000FF)<<16)|(*ptr&0xFF00FF00);
- }
- //--------------------------------------------------------------------------
- UINT32 VertexElement::convertColourValue(const Color& src,
- VertexElementType dst)
- {
- switch(dst)
- {
- #if CM_PLATFORM == CM_PLATFORM_WIN32
- default:
- #endif
- case VET_COLOUR_ARGB:
- return src.getAsARGB();
- #if CM_PLATFORM != CM_PLATFORM_WIN32
- default:
- #endif
- case VET_COLOUR_ABGR:
- return src.getAsABGR();
- };
- }
- //-----------------------------------------------------------------------------
- VertexElementType VertexElement::getBaseType(VertexElementType multiType)
- {
- switch (multiType)
- {
- case VET_FLOAT1:
- case VET_FLOAT2:
- case VET_FLOAT3:
- case VET_FLOAT4:
- return VET_FLOAT1;
- case VET_COLOUR:
- return VET_COLOUR;
- case VET_COLOUR_ABGR:
- return VET_COLOUR_ABGR;
- case VET_COLOUR_ARGB:
- return VET_COLOUR_ARGB;
- case VET_SHORT1:
- case VET_SHORT2:
- case VET_SHORT3:
- case VET_SHORT4:
- return VET_SHORT1;
- case VET_UBYTE4:
- return VET_UBYTE4;
- };
- // To keep compiler happy
- return VET_FLOAT1;
- }
- //-----------------------------------------------------------------------------
- VertexDeclaration::VertexDeclaration()
- {
- }
- //-----------------------------------------------------------------------------
- VertexDeclaration::~VertexDeclaration()
- {
- }
- //-----------------------------------------------------------------------------
- const VertexDeclaration::VertexElementList& VertexDeclaration::getElements(void) const
- {
- return mElementList;
- }
- //-----------------------------------------------------------------------------
- const VertexElement& VertexDeclaration::addElement(unsigned short source,
- size_t offset, VertexElementType theType,
- VertexElementSemantic semantic, unsigned short index)
- {
- // Refine colour type to a specific type
- if (theType == VET_COLOUR)
- {
- theType = VertexElement::getBestColourVertexElementType();
- }
- mElementList.push_back(
- VertexElement(source, offset, theType, semantic, index)
- );
- return mElementList.back();
- }
- //-----------------------------------------------------------------------------
- const VertexElement& VertexDeclaration::insertElement(unsigned short atPosition,
- unsigned short source, size_t offset, VertexElementType theType,
- VertexElementSemantic semantic, unsigned short index)
- {
- if (atPosition >= mElementList.size())
- {
- return addElement(source, offset, theType, semantic, index);
- }
- VertexElementList::iterator i = mElementList.begin();
- for (unsigned short n = 0; n < atPosition; ++n)
- ++i;
- i = mElementList.insert(i,
- VertexElement(source, offset, theType, semantic, index));
- return *i;
- }
- //-----------------------------------------------------------------------------
- const VertexElement* VertexDeclaration::getElement(unsigned short index)
- {
- assert(index < mElementList.size() && "Index out of bounds");
- VertexElementList::iterator i = mElementList.begin();
- for (unsigned short n = 0; n < index; ++n)
- ++i;
- return &(*i);
- }
- //-----------------------------------------------------------------------------
- void VertexDeclaration::removeElement(unsigned short elem_index)
- {
- assert(elem_index < mElementList.size() && "Index out of bounds");
- VertexElementList::iterator i = mElementList.begin();
- for (unsigned short n = 0; n < elem_index; ++n)
- ++i;
- mElementList.erase(i);
- }
- //-----------------------------------------------------------------------------
- void VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index)
- {
- VertexElementList::iterator ei, eiend;
- eiend = mElementList.end();
- for (ei = mElementList.begin(); ei != eiend; ++ei)
- {
- if (ei->getSemantic() == semantic && ei->getIndex() == index)
- {
- mElementList.erase(ei);
- break;
- }
- }
- }
- //-----------------------------------------------------------------------------
- void VertexDeclaration::removeAllElements(void)
- {
- mElementList.clear();
- }
- //-----------------------------------------------------------------------------
- void VertexDeclaration::modifyElement(unsigned short elem_index,
- unsigned short source, size_t offset, VertexElementType theType,
- VertexElementSemantic semantic, unsigned short index)
- {
- assert(elem_index < mElementList.size() && "Index out of bounds");
- VertexElementList::iterator i = mElementList.begin();
- std::advance(i, elem_index);
- (*i) = VertexElement(source, offset, theType, semantic, index);
- }
- //-----------------------------------------------------------------------------
- const VertexElement* VertexDeclaration::findElementBySemantic(
- VertexElementSemantic sem, unsigned short index)
- {
- VertexElementList::const_iterator ei, eiend;
- eiend = mElementList.end();
- for (ei = mElementList.begin(); ei != eiend; ++ei)
- {
- if (ei->getSemantic() == sem && ei->getIndex() == index)
- {
- return &(*ei);
- }
- }
- return NULL;
- }
- //-----------------------------------------------------------------------------
- VertexDeclaration::VertexElementList VertexDeclaration::findElementsBySource(
- unsigned short source)
- {
- VertexElementList retList;
- VertexElementList::const_iterator ei, eiend;
- eiend = mElementList.end();
- for (ei = mElementList.begin(); ei != eiend; ++ei)
- {
- if (ei->getSource() == source)
- {
- retList.push_back(*ei);
- }
- }
- return retList;
- }
- //-----------------------------------------------------------------------------
- size_t VertexDeclaration::getVertexSize(unsigned short source)
- {
- VertexElementList::const_iterator i, iend;
- iend = mElementList.end();
- size_t sz = 0;
- for (i = mElementList.begin(); i != iend; ++i)
- {
- if (i->getSource() == source)
- {
- sz += i->getSize();
- }
- }
- return sz;
- }
- //-----------------------------------------------------------------------------
- VertexDeclarationPtr VertexDeclaration::clone(HardwareBufferManagerBase* mgr)
- {
- HardwareBufferManagerBase* pManager = mgr ? mgr : HardwareBufferManager::instancePtr();
- VertexDeclarationPtr ret = pManager->createVertexDeclaration();
- VertexElementList::const_iterator i, iend;
- iend = mElementList.end();
- for (i = mElementList.begin(); i != iend; ++i)
- {
- ret->addElement(i->getSource(), i->getOffset(), i->getType(), i->getSemantic(), i->getIndex());
- }
- return ret;
- }
- //-----------------------------------------------------------------------------
- // Sort routine for VertexElement
- bool VertexDeclaration::vertexElementLess(const VertexElement& e1, const VertexElement& e2)
- {
- // Sort by source first
- if (e1.getSource() < e2.getSource())
- {
- return true;
- }
- else if (e1.getSource() == e2.getSource())
- {
- // Use ordering of semantics to sort
- if (e1.getSemantic() < e2.getSemantic())
- {
- return true;
- }
- else if (e1.getSemantic() == e2.getSemantic())
- {
- // Use index to sort
- if (e1.getIndex() < e2.getIndex())
- {
- return true;
- }
- }
- }
- return false;
- }
- void VertexDeclaration::sort(void)
- {
- mElementList.sort(VertexDeclaration::vertexElementLess);
- }
- //-----------------------------------------------------------------------------
- void VertexDeclaration::closeGapsInSource(void)
- {
- if (mElementList.empty())
- return;
- // Sort first
- sort();
- VertexElementList::iterator i, iend;
- iend = mElementList.end();
- unsigned short targetIdx = 0;
- unsigned short lastIdx = getElement(0)->getSource();
- unsigned short c = 0;
- for (i = mElementList.begin(); i != iend; ++i, ++c)
- {
- VertexElement& elem = *i;
- if (lastIdx != elem.getSource())
- {
- targetIdx++;
- lastIdx = elem.getSource();
- }
- if (targetIdx != elem.getSource())
- {
- modifyElement(c, targetIdx, elem.getOffset(), elem.getType(),
- elem.getSemantic(), elem.getIndex());
- }
- }
- }
- //-----------------------------------------------------------------------------
- unsigned short VertexDeclaration::getMaxSource(void) const
- {
- VertexElementList::const_iterator i, iend;
- iend = mElementList.end();
- unsigned short ret = 0;
- for (i = mElementList.begin(); i != iend; ++i)
- {
- if (i->getSource() > ret)
- {
- ret = i->getSource();
- }
- }
- return ret;
- }
- /************************************************************************/
- /* SERIALIZATION */
- /************************************************************************/
- RTTITypeBase* VertexDeclaration::getRTTIStatic()
- {
- return VertexDeclarationRTTI::instance();
- }
- RTTITypeBase* VertexDeclaration::getRTTI() const
- {
- return getRTTIStatic();
- }
- //-----------------------------------------------------------------------------
- VertexBufferBinding::VertexBufferBinding() : mHighIndex(0)
- {
- }
- //-----------------------------------------------------------------------------
- VertexBufferBinding::~VertexBufferBinding()
- {
- unsetAllBindings();
- }
- //-----------------------------------------------------------------------------
- void VertexBufferBinding::setBinding(unsigned short index, const HardwareVertexBufferPtr& buffer)
- {
- // NB will replace any existing buffer ptr at this index, and will thus cause
- // reference count to decrement on that buffer (possibly destroying it)
- mBindingMap[index] = buffer;
- mHighIndex = std::max(mHighIndex, (unsigned short)(index+1));
- }
- //-----------------------------------------------------------------------------
- void VertexBufferBinding::unsetBinding(unsigned short index)
- {
- VertexBufferBindingMap::iterator i = mBindingMap.find(index);
- if (i == mBindingMap.end())
- {
- CM_EXCEPT(ItemIdentityException,
- "Cannot find buffer binding for index " + toString(index));
- }
- mBindingMap.erase(i);
- }
- //-----------------------------------------------------------------------------
- void VertexBufferBinding::unsetAllBindings(void)
- {
- mBindingMap.clear();
- mHighIndex = 0;
- }
- //-----------------------------------------------------------------------------
- const VertexBufferBinding::VertexBufferBindingMap&
- VertexBufferBinding::getBindings(void) const
- {
- return mBindingMap;
- }
- //-----------------------------------------------------------------------------
- const HardwareVertexBufferPtr& VertexBufferBinding::getBuffer(unsigned short index) const
- {
- VertexBufferBindingMap::const_iterator i = mBindingMap.find(index);
- if (i == mBindingMap.end())
- {
- CM_EXCEPT(ItemIdentityException, "No buffer is bound to that index.");
- }
- return i->second;
- }
- //-----------------------------------------------------------------------------
- bool VertexBufferBinding::isBufferBound(unsigned short index) const
- {
- return mBindingMap.find(index) != mBindingMap.end();
- }
- //-----------------------------------------------------------------------------
- unsigned short VertexBufferBinding::getLastBoundIndex(void) const
- {
- return mBindingMap.empty() ? 0 : mBindingMap.rbegin()->first + 1;
- }
- //-----------------------------------------------------------------------------
- bool VertexBufferBinding::hasGaps(void) const
- {
- if (mBindingMap.empty())
- return false;
- if (mBindingMap.rbegin()->first + 1 == (int) mBindingMap.size())
- return false;
- return true;
- }
- //-----------------------------------------------------------------------------
- void VertexBufferBinding::closeGaps(BindingIndexMap& bindingIndexMap)
- {
- bindingIndexMap.clear();
- VertexBufferBindingMap newBindingMap;
- VertexBufferBindingMap::const_iterator it;
- UINT16 targetIndex = 0;
- for (it = mBindingMap.begin(); it != mBindingMap.end(); ++it, ++targetIndex)
- {
- bindingIndexMap[it->first] = targetIndex;
- newBindingMap[targetIndex] = it->second;
- }
- mBindingMap.swap(newBindingMap);
- mHighIndex = targetIndex;
- }
- }
|