| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- /*
- -----------------------------------------------------------------------------
- The MIT License (MIT)
- Copyright (c) 2013-08-17 Tobias Peters <tobias.peters@kreativeffekt.at>
- 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 "common/QGearsManualObject.h"
- #include <cstring>
- #include <OgreException.h>
- #include <OgreHardwareBufferManager.h>
- #include <OgreRoot.h>
- namespace QGears
- {
- //-------------------------------------------------------------------------
- ManualObject::ManualObject( Ogre::Mesh *mesh ) :
- m_mesh( mesh )
- ,m_section( nullptr )
- ,m_bbox( mesh->getBounds() )
- ,m_radius( mesh->getBoundingSphereRadius() )
- ,m_position( nullptr )
- ,m_normal( nullptr )
- ,m_colour( nullptr )
- ,m_texture_coordinate( nullptr )
- ,m_index( nullptr )
- ,colour_type( Ogre::VertexElement::getBestColourVertexElementType() )
- {
- }
- //-------------------------------------------------------------------------
- ManualObject::~ManualObject()
- {
- }
- //-------------------------------------------------------------------------
- template<typename BufferType>
- BufferType*
- ManualObject::createBuffer( const BufferBinding binding
- ,Ogre::VertexElementType type
- ,Ogre::VertexElementSemantic semantic )
- {
- Ogre::VertexDeclaration* decl = m_section->vertexData->vertexDeclaration;
- Ogre::VertexBufferBinding* bind = m_section->vertexData->vertexBufferBinding;
- decl->addElement( binding, 0, type, semantic );
- size_t vertex_size( decl->getVertexSize( binding ) );
- VertexBuffer buffer = Ogre::HardwareBufferManager::getSingleton()
- .createVertexBuffer( vertex_size
- ,m_section->vertexData->vertexCount
- ,Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY);
- bind->setBinding( binding, buffer );
- m_vertex_buffers[binding] = buffer;
- return static_cast<BufferType*>( buffer->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::createPositionBuffer()
- {
- m_position = createBuffer<Ogre::Vector3>( BB_POSITION, Ogre::VET_FLOAT3, Ogre::VES_POSITION );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::createNormalBuffer()
- {
- m_normal = createBuffer<Ogre::Vector3>( BB_NORMAL, Ogre::VET_FLOAT3, Ogre::VES_NORMAL );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::createColourBuffer()
- {
- m_colour = createBuffer<uint32>( BB_COLOUR, colour_type, Ogre::VES_DIFFUSE );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::createTextureCoordinateBuffer()
- {
- m_texture_coordinate = createBuffer<Ogre::Vector2>( BB_TEXTURE, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::createIndexBuffer()
- {
- m_index_buffer = Ogre::HardwareBufferManager::getSingleton()
- .createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT
- ,m_section->indexData->indexCount
- ,Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY );
- void *data( m_index_buffer->lock( Ogre::HardwareBuffer::HBL_DISCARD ) );
- m_index = static_cast< uint16* >( data );
- m_section->indexData->indexBuffer = m_index_buffer;
- }
- //-------------------------------------------------------------------------
- template<typename BufferSharedPtr>
- void
- ManualObject::resetBuffer( BufferSharedPtr &buffer ) const
- {
- if( buffer.isNull() ) return;
- if( buffer->isLocked() )
- {
- buffer->unlock();
- }
- buffer.setNull();
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::resetBuffers()
- {
- for( int i(BINDING_COUNT); i--; )
- {
- resetBuffer( m_vertex_buffers[i] );
- }
- resetBuffer( m_index_buffer );
- m_position = nullptr;
- m_normal = nullptr;
- m_colour = nullptr;
- m_texture_coordinate = nullptr;
- m_index = nullptr;
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::begin( const String &name, const String &material_name
- ,size_t vertex_count, size_t index_count )
- {
- if( m_mesh == nullptr )
- {
- OGRE_EXCEPT( Ogre::Exception::ERR_INVALIDPARAMS,
- "You cannot begin a section without a Mesh",
- "ManualObject::begin");
- }
- if( m_section != nullptr )
- {
- OGRE_EXCEPT( Ogre::Exception::ERR_INVALIDPARAMS,
- "You cannot begin a section without ending the old one first",
- "ManualObject::begin");
- }
- if( vertex_count == 0 )
- {
- OGRE_EXCEPT( Ogre::Exception::ERR_INVALIDPARAMS,
- "You cannot begin with a vertex count of 0",
- "ManualObject::begin");
- }
- m_section = m_mesh->createSubMesh( name );
- m_section->setMaterialName( material_name );
- m_section->useSharedVertices = false;
- m_section->operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST;
- m_section->vertexData = new Ogre::VertexData();
- m_section->vertexData->vertexStart = 0;
- m_section->vertexData->vertexCount = vertex_count;
- m_section->indexData = new Ogre::IndexData();
- m_section->indexData->indexStart = 0;
- m_section->indexData->indexCount = index_count;
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::position( const Ogre::Vector3 &position )
- {
- if( m_position == nullptr )
- {
- createPositionBuffer();
- }
- *(m_position++) = position;
- m_bbox.merge( position );
- m_radius = std::max( m_radius, position.length() );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::normal( const Ogre::Vector3 &normal )
- {
- if( m_normal == nullptr )
- {
- createNormalBuffer();
- }
- *(m_normal++) = normal;
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::colour( const Ogre::ColourValue &colour )
- {
- if( m_colour == nullptr )
- {
- createColourBuffer();
- }
- *(m_colour++) = Ogre::VertexElement::convertColourValue( colour, colour_type );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::textureCoord( const Ogre::Vector2 &texture_coordinate )
- {
- if( m_texture_coordinate == nullptr )
- {
- createTextureCoordinateBuffer();
- }
- *(m_texture_coordinate++) = texture_coordinate;
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::index( const uint32 idx )
- {
- if( m_index == nullptr )
- {
- createIndexBuffer();
- }
- *(m_index++) = idx;
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::bone( const uint32 idx, const uint16 bone_handle
- ,const Ogre::Real weight )
- {
- Ogre::VertexBoneAssignment vba;
- vba.vertexIndex = idx;
- vba.boneIndex = bone_handle;
- vba.weight = weight;
- m_section->addBoneAssignment( vba );
- }
- //-------------------------------------------------------------------------
- void
- ManualObject::end()
- {
- if( m_section == nullptr )
- {
- OGRE_EXCEPT( Ogre::Exception::ERR_INVALIDPARAMS,
- "You cannot end a section without beginning one first",
- "ManualObject::end");
- }
- m_mesh->_setBounds( m_bbox );
- m_mesh->_setBoundingSphereRadius( m_radius );
- m_section = nullptr;
- resetBuffers();
- }
- //-------------------------------------------------------------------------
- }
|