OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: Geometry Batching
View page
Source of version: 14
(current)
This article intent is to give a practical code demonstrating the usage of [http://www.ogre3d.org/docs/manual/manual_49.html#SEC264|Hardware Buffers] and to be able to understand how the ((PagedGeometry Engine)) works aka [https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/forests/|forests ogreaddon]. This tutorial is not meant to replace the [http://www.ogre3d.org/docs/manual/|Ogre Manual] but to give a practical code to toy with those classes. As you will notice when you study the ((PagedGeometry)) engine the code below is a rip-off of the engine. I am greatly indebted to ((User:JohnJ|JohnJ)) without his code I wouldn't have grasped the concepts. {img src="img/wiki_up/Forum_icon_question2.gif" alt="Forum icon question2.gif"} Please, use [http://www.ogre3d.org/forums/viewtopic.php?f=5&t=49028|this forum thread] to discuss problems, suggestions, etc. {maketoc} !!What is Geometry Batching? Batching is the process of rendering sending massive amounts of ((mesh))es by accessing directly the graphics memory. For simple usage using ((Intermediate Tutorial 5|Static Geometry)) is ideal. However sometime you need to be able to use more fundamental methods (such as if you want to create a specific scene manager, have more control on the mesh detail based on ((-LOD)), ...). PagedGeometry is a good example. !!Vertex & Buffer structure __TODO__ A nice UML diagram :D ~tc~ BEGIN TABLE ~/tc~ || Classes | Structure | Explanation __VertexData__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1VertexData.html|api],%%%[http://www.ogre3d.org/docs/manual/manual_56.html#SEC272|manual]|VertexDeclaration* vertexDeclaration;%%%VertexBufferBinding* vertexBufferBinding; %%%size_t vertexStart; size_t vertexCount; %%%HardwareAnimationDataList hwAnimationDataList; %%%size_t hwAnimationItemUsed; |Collects vertex sources information.%%%''vertexCount'' is the number of vertices. ''hwAnimationDataList'' is usef for morph/pose animation. __IndexData__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1IndexData.html|api],%%%[ manual]|size_t indexStart;%%%size_t indexCount; |''indexStart'': buffer position to start from during an Operation%%%''indexCount'': number of indexes to use from the buffer __HardwareVertexBuffer__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1HardwareVertexBuffer.html|api],%%%[http://www.ogre3d.org/docs/manual/manual_55.html#SEC271|manual]|size_t mNumVertices; %%%size_t mVertexSize; |''mVertexSize'': size of a __single__ vertex in this buffer. __HardwareIndexBuffer__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1HardwareIndexBuffer.html|api],%%%[http://www.ogre3d.org/docs/manual/manual_60.html#SEC279|manual]|enum IndexType; %%%enum Usage; %%%enum LockOptions; |... __VertexBufferBinding__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1VertexBufferBinding.html|api],%%%[http://www.ogre3d.org/docs/manual/manual_58.html#SEC275|manual]| std::map<ushort, %%%HardwareVertexBufferSharedPtr> VertexBufferBindingMap; %%% VertexBufferBindingMap mBindingMap; %%% ushort mHightIndex;|... __VertexDeclaration__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1VertexDeclaration.html|api],%%%[http://www.ogre3d.org/docs/manual/manual_57.html#SEC273|manual]| typdef std::list<VertexElement>%%%VertexElementList; %%% VertexElementList mElementList; |''VertexElement'' should be added in a precise order: see below. __VertexElement__%%%[http://www.ogre3d.org/docs/api/html/classOgre_1_1VertexElement.html|api],%%%[ manual]| ushort mSource; %%% size_t mOffset; %%% VertexElementType mType; %%% VertexElementSemantic mSemantics; %%% ushort mIndex; %%%|todo|| ~tc~ END OF TABLE ~/tc~ Some important points need to be taken in consideration when implementing [http://www.ogre3d.org/docs/api/html/classOgre_1_1VertexDeclaration.html#_details|VertexDeclaration]: ''You should be aware that the ordering and structure of the VertexDeclaration can be very important on DirectX with older cards,so if you want to maintain maximum compatibility with all render systems and all cards you should be careful to follow these rules:'' # ((-Vertex))Elements should be added in the following order, and the order of the elements within a shared buffer should be as follows: position, blending weights, normals, diffuse colours, specular colours, texture coordinates (in order, with no gaps) # You must not have unused gaps in your buffers which are not referenced by any VertexElement # You must not cause the buffer & offset settings of 2 VertexElements to overlap !!Sample Code Usage The code below will demonstrate how to make a [http://www.ogre3d.org/docs/api/html/classOgre_1_1MovableObject.html|MovableObject] which uses batched geometry. The code can be compiled as a static lib and used very simply. It will display a simple cube (no texture, no color). Adding texture and color could be done in a second part. {CODE(wrap="1", colors="c++")} Ogre::SceneNode* sn = sceneManager->getRootSceneNode() ->createChildSceneNode(Ogre::Vector3(0,0,0)); Ogre::BatchedGeometry* object = new Ogre::BatchedGeometry(sceneManager, sn); object->addObject(Ogre::Vector3::ZERO); object->build(); {CODE} To add your own geometry you need to modify the code between : {CODE(wrap="1", colors="c++")} // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ {CODE} __Note__: The code is a bare minimum rip-off from the PagedGeometry Engine source also know as the [https://ogreaddons.svn.sourceforge.net/svnroot/ogreaddons/trunk/forests/|forests ogreaddons]. !!Code Structure The code is only composed of two classes: BatchedGeometry and Batch. ''BatchedGeometry'' derives from a [http://www.ogre3d.org/docs/api/html/classOgre_1_1MovableObject.html|MovableObject] which means you can easily manipulate it in your scenes. Its purpose is to collect the various sub-part composing the geometry you want to batch. An very important point to note is that batches should be grouped together to use the hardware at its fullest. This is the reason of the BatchedGeometry::getFormatString() method in the PagedGeometry Engine. I didn't implement this (yet) to keep the code... simple. ''Batch'' derives from a [http://www.ogre3d.org/docs/api/html/classOgre_1_1Renderable.html|Renderable]. This is the class that access the hardware buffer during the rendering phase. !!Code Source !!!OgreBatchedGeometry.h {CODE(wrap="1", colors="c++")} #ifndef __OGE_BATCHEDGEOMETRY_H__ #define __OGE_BATCHEDGEOMETRY_H__ #include "OgreBatch.h" #include "OGRE/OgrePrerequisites.h" #include "OGRE/OgreMovableObject.h" namespace Ogre { /** */ class BatchedGeometry: public MovableObject { private: Vector3 mCenter; Real mRadius; AxisAlignedBox mBounds; bool mBoundsUndefined; Real mMinDistanceSquared; // Why not using MovableObject::mBeyondFarDistance ? bool mWithinFarDistance; /// Stores a list of Batchs, using a format string /// (generated with getGeometryFormatString()) as the key value typedef std::map<String, Batch*> BatchMap; BatchMap mBatchs; bool mIsBuilt; SceneManager* mSceneManager; SceneNode* mSceneNode; SceneNode* mParentSceneNode; public: typedef Ogre::MapIterator<BatchMap> BatchIterator; public: BatchedGeometry(SceneManager* mgr, SceneNode* parentSceneNode); virtual ~BatchedGeometry(); // ---- Abstract method that need to be implemented ---- const String& getMovableType() const { static String s = "BatchedGeometry"; return s; } const AxisAlignedBox& getBoundingBox() const { return mBounds; } Real getBoundingRadius() const { return mRadius; } const Vector3& getCenter() const { return mCenter; } const SceneNode* getSceneNode() const { return mSceneNode; } void _updateRenderQueue(RenderQueue* queue); void visitRenderables(Renderable::Visitor* visitor, bool debugRenderables) {} // ------------------------------------------------------ void clear(); void build(); bool isVisible(); /** Internal method to notify the object of the camera * to be used for the next rendering operation. */ void _notifyCurrentCamera(Camera* cam); void addSelfToRenderQueue(RenderQueue* queue, uint8 group); inline Real const getMinDistanceSquared() const { return mMinDistanceSquared; } /// Convert from the given global position to the local /// coordinate system of the parent scene node. Vector3 convertToLocal(const Vector3& globalVec) const; BatchIterator getBatchIterator() const; // The main method of the class! void addObject(const Vector3& position, const Quaternion& orientation = Quaternion::IDENTITY, const Vector3& scale = Vector3::UNIT_SCALE); ///Generate a format string that uniquely identifies /// this material & vertex/index format // TODO String getFormatString(Ogre::SubEntity* ent); }; } #endif {CODE} !!!OgreBatchedGeometry.cpp {CODE(wrap="1", colors="c++")} #include "OgreBatchedGeometry.h" #include "OGRE/OgreCamera.h" #include "OGRE/OgreSceneNode.h" #include "OGRE/OgreSceneManager.h" namespace Ogre { //----------------------------------------------------------------------------- BatchedGeometry::BatchedGeometry(SceneManager* mgr, SceneNode* parentSceneNode) : mBoundsUndefined(true), mMinDistanceSquared(0), mWithinFarDistance(false), mSceneManager(mgr), mSceneNode(0), mParentSceneNode(parentSceneNode) { clear(); COUT("BatchedGeometry created") } //----------------------------------------------------------------------------- BatchedGeometry::~BatchedGeometry() { clear(); COUT("BatchedGeometry destroyed") } //----------------------------------------------------------------------------- void BatchedGeometry::clear() { // Remove the batch from the scene if (mSceneNode) { mSceneNode->removeAllChildren(); mSceneManager->destroySceneNode(mSceneNode->getName()); mSceneNode = 0; } // Reset bounds information mBoundsUndefined = true; //mBounds = AxisAlignedBox::BOX_NULL; why not? mCenter = Vector3::ZERO; mRadius = 0; // Delete each batch for (BatchMap::iterator i = mBatchs.begin(); i != mBatchs.end(); ++i) { delete i->second; } mBatchs.clear(); mIsBuilt = false; } //----------------------------------------------------------------------------- void BatchedGeometry::build() { if (mIsBuilt) OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "Invalid call to build() - celestial object is already batched (call clear() first)", "BatchedGeometry::build()"); if (mBatchs.size() != 0) { // Finish bounds information mCenter = mBounds.getCenter(); //Center the bounding box mBounds.setMinimum(mBounds.getMinimum() - mCenter); mBounds.setMaximum(mBounds.getMaximum() - mCenter); //Calculate BB radius mRadius = mBounds.getMaximum().length(); // Create scene node mSceneNode = mParentSceneNode->createChildSceneNode(mCenter); // Build each batch for (BatchMap::iterator i = mBatchs.begin(); i != mBatchs.end(); ++i) { i->second->build(); } } // Attach the batch to the scene node mSceneNode->attachObject(this); // Debug mSceneNode->showBoundingBox(true); // TODO param mIsBuilt = true; } //----------------------------------------------------------------------------- void BatchedGeometry::_updateRenderQueue(RenderQueue* queue) { if (isVisible()) { // If appropriate ask each batch to add itself // to the render queue for (BatchMap::iterator i = mBatchs.begin(); i != mBatchs.end(); ++i) { i->second->addSelfToRenderQueue(queue, getRenderQueueGroup()); } } } //----------------------------------------------------------------------------- bool BatchedGeometry::isVisible() { // mVisible is an MovableObject attribute return mVisible && mWithinFarDistance; } //----------------------------------------------------------------------------- void BatchedGeometry::_notifyCurrentCamera(Camera* cam) { if (getRenderingDistance() == 0) { mWithinFarDistance = true; } else { //Calculate camera distance Vector3 camVec = convertToLocal( cam->getDerivedPosition()) - mCenter; Real centerDistanceSquared = camVec.squaredLength(); mMinDistanceSquared = std::max(0.0f, centerDistanceSquared - (mRadius * mRadius)); // Note: centerDistanceSquared measures the distance // between the camera and the center of the Batch, // while minDistanceSquared measures the closest distance // between the camera and the closest edge of the // geometry's bounding sphere. //Determine whether the BatchedGeometry is within / the far rendering distance mWithinFarDistance = mMinDistanceSquared <= Math::Sqr(getRenderingDistance()); } } //----------------------------------------------------------------------------- Ogre::Vector3 BatchedGeometry::convertToLocal(const Vector3& globalVec) const { assert(mParentSceneNode); //Convert from the given global position to // the local coordinate system of the parent scene node. return (mParentSceneNode->getOrientation().Inverse() * globalVec); } //----------------------------------------------------------------------------- BatchedGeometry::BatchIterator BatchedGeometry::getBatchIterator() const { return BatchIterator((BatchMap&)mBatchs); } //----------------------------------------------------------------------------- void BatchedGeometry::addObject(const Vector3& position, const Quaternion& orientation, const Vector3& scale) { // Create geometry // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ String format = "aa"; // TODO = getFormatString(...) // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Batch* batch; /* TODO BatchIterator iter = mBatchs.find(format); if (iter != mBatchs.end()) batch = iter->second; else { */ batch = new Batch(this); mBatchs.insert(std::pair<String, Batch*>(format, batch)); // } // cf. PagedGeometry addSubEntity() batch->addSub( position, orientation, scale ); // Update the bounding box Matrix4 mat(orientation); mat.setScale(scale); AxisAlignedBox entBounds; // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // entBounds = ent->getBoundingBox(); entBounds.setMinimum(Vector3(-100,-100,-100)); entBounds.setMaximum(Vector3( 100, 100, 100)); // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ entBounds.transform(mat); if (mBoundsUndefined) { mBounds.setMinimum(entBounds.getMinimum() + position); mBounds.setMaximum(entBounds.getMaximum() + position); mBoundsUndefined = false; } else { Vector3 min = mBounds.getMinimum(); Vector3 max = mBounds.getMaximum(); min.makeFloor(entBounds.getMinimum() + position); max.makeCeil(entBounds.getMaximum() + position); mBounds.setMinimum(min); mBounds.setMaximum(max); } } //----------------------------------------------------------------------------- } {CODE} !!!OgreBatch.h {CODE(wrap="1", colors="c++")} #ifndef __OGRE_BATCH_H__ #define __OGRE_BATCH_H__ #include "OGRE/OgrePrerequisites.h" #include "OGRE/OgreMovableObject.h" #include "OGRE/OgreMaterialManager.h" #define COUT(x) std::cout << x << std::endl; namespace Ogre { // Forward definition class BatchedGeometry; /* * */ class Batch : public Renderable { private: bool mIsBuilt; VertexData* mVertexData; IndexData* mIndexData; BatchedGeometry* mParent; MaterialPtr mMaterial; // NOTE : This should be recalculated every frame Technique* mBestTechnique; // Should those be part of a struct? Vector3 mPosition; Quaternion mOrientation; Vector3 mScale; ColourValue mColour; public: Batch(BatchedGeometry* parent); //, SubEntity* ent); ~Batch(); void build(); void clear(); void setMaterial(MaterialPtr& mat) { mMaterial = mat; } void setMaterialName(const String& mat) { mMaterial = MaterialManager::getSingleton().getByName(mat); } inline String getMaterialName() const { return mMaterial->getName(); } const MaterialPtr& getMaterial() const { return mMaterial; } Technique* getTechnique() const { return mBestTechnique; } void getWorldTransforms(Matrix4* xform) const; const Quaternion& getWorldOrientation() const; const Vector3& getWorldPosition() const; bool castsShadows() const; const LightList& getLights() const; void addSelfToRenderQueue(RenderQueue* queue, uint8 group); void getRenderOperation(RenderOperation& operation); Real getSquaredViewDepth(const Camera* cam) const; /** * This function is used to make a unique clone of materials, * since the materials will be modified by the batch system * (and it wouldn't be good to modify the original materials * that the user may be using somewhere else). */ Material* getMaterialClone(Material* material); // cf. PagedGeometry method: // void BatchedGeometry::SubBatch::addSubEntity( // SubEntity *ent, ....); void addSub(const Vector3& position, const Quaternion& orientation, const Vector3& scale, const ColourValue& color = ColourValue::White); }; } #endif {CODE} !!!OgreBatch.cpp {CODE(wrap="1", colors="c++")} #include "OgreBatch.h" #include "OgreBatchedGeometry.h" #include "OGRE/OgreCamera.h" #include "OGRE/OgreSceneNode.h" #include "OGRE/OgreHardwareBufferManager.h" #include "OGRE/OgreTechnique.h" #include "OGRE/OgreRoot.h" #include "OGRE/OgreRenderSystem.h" #include "OGRE/OgreColourValue.h" namespace Ogre { //----------------------------------------------------------------------------- Batch::Batch(BatchedGeometry* parent) : mParent(parent) { mIsBuilt = false; // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // See PagedGeometry BatchedGeometry::SubBatch::SubBatch() // Material *origMat = // ((MaterialPtr)MaterialManager::getSingleton().getByName( // ent->getMaterialName())).getPointer(); // mMaterial = // MaterialManager::getSingleton().getByName( // getMaterialClone(origMat)->getName()); // mMaterial = MaterialManager::getSingleton().create( // "Test/ColourTest", // ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mMaterial->getTechnique(0)->getPass(0) ->setVertexColourTracking(TVC_AMBIENT); mMaterial->getTechnique(0)->getPass(0)->setSpecular(0,0,0,1); // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // See PagedGeometry to see how to clone PARTS of the entity data mVertexData = new VertexData(); mIndexData = new IndexData(); // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Reset vertex/index count mVertexData->vertexStart = 0; mVertexData->vertexCount = 0; mIndexData->indexStart = 0; mIndexData->indexCount = 0; } //----------------------------------------------------------------------------- Batch::~Batch() { clear(); delete mVertexData; delete mIndexData; } //----------------------------------------------------------------------------- void Batch::addSelfToRenderQueue(RenderQueue* queue, uint8 group) { if (mIsBuilt) { // Update material technique based on camera distance assert(!mMaterial.isNull()); mBestTechnique = mMaterial->getBestTechnique( mMaterial->getLodIndexSquaredDepth( mParent->getMinDistanceSquared())); queue->addRenderable(this, group); } } //----------------------------------------------------------------------------- bool Batch::castsShadows() const { return mParent->getCastShadows(); } //----------------------------------------------------------------------------- void Batch::clear() { // If built, delete it if (mIsBuilt) { //Delete buffers mIndexData->indexBuffer.setNull(); mVertexData->vertexBufferBinding->unsetAllBindings(); // NOTE: If you are adding the elements each time // you must remove the previous one before // mVertexData->vertexDeclaration->removeAllElements(); //Reset vertex/index count mVertexData->vertexStart = 0; mVertexData->vertexCount = 0; mIndexData->indexStart = 0; mIndexData->indexCount = 0; } mIsBuilt = false; } //----------------------------------------------------------------------------- Material* Batch::getMaterialClone(Material* material) { String name = material->getName() + "_Batch"; MaterialPtr clone = MaterialManager::getSingleton().getByName( name ); if (clone.isNull()) clone = material->clone(name); return clone.getPointer(); } //----------------------------------------------------------------------------- void Batch::getRenderOperation(RenderOperation& operation) { operation.operationType = RenderOperation::OT_TRIANGLE_LIST; operation.srcRenderable = this; operation.useIndexes = true; operation.vertexData = mVertexData; operation.indexData = mIndexData; /* debug COUT(" 1 " << mVertexData->vertexCount) COUT(" 1 " << mVertexData->vertexCount) COUT(" 2 " << mVertexData->vertexDeclaration->getElementCount()) COUT(" 3 " << mVertexData->vertexDeclaration->getVertexSize(0)) COUT(" 4 " << mVertexData->vertexDeclaration->getElement(1)->getIndex()) COUT(" 5 " << mVertexData->vertexDeclaration->getElement(1)->getSource()) COUT(" 5 " << mIndexData->indexCount) COUT(" 6 " << mIndexData->indexBuffer->getIndexSize()) COUT(" 7 " << mIndexData->indexBuffer->getNumIndexes()) */ } //----------------------------------------------------------------------------- Real Batch::getSquaredViewDepth(const Camera *camera) const { Vector3 pos = mParent->convertToLocal( camera->getDerivedPosition()) - mParent->getCenter(); return pos.squaredLength(); } //----------------------------------------------------------------------------- const LightList& Batch::getLights() const { return mParent->queryLights(); } //----------------------------------------------------------------------------- void Batch::getWorldTransforms(Matrix4* xform) const { *xform = mParent->_getParentNodeFullTransform(); } //----------------------------------------------------------------------------- const Quaternion& Batch::getWorldOrientation() const { return mParent->getSceneNode()->_getDerivedOrientation(); } //----------------------------------------------------------------------------- const Vector3& Batch::getWorldPosition() const { return mParent->getSceneNode()->_getDerivedPosition(); } //----------------------------------------------------------------------------- void Batch::addSub(const Vector3& position, const Quaternion& orientation, const Vector3& scale, const ColourValue& color) { assert(!mIsBuilt); // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Use a geometry data struct to pass the data mVertexData->vertexCount = 8; mIndexData->indexCount = 36; // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ mPosition = position; mOrientation = orientation; mScale = scale; mColour = color; VertexElementType format = Root::getSingleton().getRenderSystem() ->getColourVertexElementType(); switch (format) { case VET_COLOUR_ARGB: std::swap(mColour.r, mColour.b); break; case VET_COLOUR_ABGR: break; default: OGRE_EXCEPT(0, "Unknown RenderSystem color format", "Batch::addSub()"); break; } } //----------------------------------------------------------------------------- void Batch::build() { assert(!mIsBuilt); Vector3 batchCenter = mParent->getCenter(); // See PagedGeometry::BatchedGeometry for how to set IT_32BIT // If I understand it correctly this is dependent // on the number of vertices you want to batch HardwareIndexBuffer::IndexType destIndexType; destIndexType = HardwareIndexBuffer::IT_16BIT; // The vertex data at last // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ VertexBufferBinding *vertBinding = mVertexData->vertexBufferBinding; VertexDeclaration *vertDecl = mVertexData->vertexDeclaration; //Allocate & lock the vertex buffers HardwareVertexBufferSharedPtr buffer = HardwareBufferManager::getSingleton() .createVertexBuffer(24, 8, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vertBinding->setBinding(0, buffer); float* destPtr = static_cast<float*> (buffer->lock(HardwareBuffer::HBL_DISCARD)); // See Ogre Samples/CubeMapping/include/CubeMapping.h ! VertexDeclaration* dec = mVertexData->vertexDeclaration; size_t offset = 0; dec->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); dec->addElement(0, offset, VET_FLOAT3, VES_NORMAL); const float sqrt13 = 0.577350269f; *destPtr++ = -100; *destPtr++ = 100; *destPtr++ = -100; *destPtr++ = -sqrt13; *destPtr++ = sqrt13; *destPtr++ = -sqrt13; *destPtr++ = 100; *destPtr++ = 100; *destPtr++ = -100; *destPtr++ = sqrt13; *destPtr++ = sqrt13; *destPtr++ = -sqrt13; *destPtr++ = 100; *destPtr++ = -100; *destPtr++ = -100; *destPtr++ = sqrt13; *destPtr++ = -sqrt13; *destPtr++ = -sqrt13; *destPtr++ = -100; *destPtr++ = -100; *destPtr++ = -100; *destPtr++ = -sqrt13; *destPtr++ = -sqrt13; *destPtr++ = -sqrt13; *destPtr++ = -100; *destPtr++ = 100; *destPtr++ = 100; *destPtr++ = -sqrt13; *destPtr++ = sqrt13; *destPtr++ = sqrt13; *destPtr++ = 100; *destPtr++ = 100; *destPtr++ = 100; *destPtr++ = sqrt13; *destPtr++ = sqrt13; *destPtr++ = sqrt13; *destPtr++ = 100; *destPtr++ = -100; *destPtr++ = 100; *destPtr++ = sqrt13; *destPtr++ = -sqrt13; *destPtr++ = sqrt13; *destPtr++ = -100; *destPtr++ = -100; *destPtr++ = 100; *destPtr++ = -sqrt13; *destPtr++ = -sqrt13; *destPtr++ = sqrt13; //Allocate the index buffer mIndexData->indexBuffer = HardwareBufferManager::getSingleton() .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 36, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // As an alternative you can lock the buffer your self // and copy the data "manually" //uint16* indexBuffer16 = static_cast<uint16*> // (mIndexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); uint16 faces[36] = { 0,2,3, 0,1,2, 1,6,2, 1,5,6, 4,6,5, 4,7,6, 0,7,4, 0,3,7, 0,5,1, 0,4,5, 2,7,3, 2,6,7 }; //for (int i=0; i<36; ++i) //{ // *indexBuffer16++ = static_cast<uint16>(faces[i]); //} COUT(mIndexData->indexBuffer->getSizeInBytes()); COUT(sizeof(faces)); mIndexData->indexBuffer->writeData( 0, mIndexData->indexBuffer->getSizeInBytes(), faces, true); // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ //mIndexData->indexBuffer->unlock(); buffer->unlock(); mMaterial->load(); // TODO Not sure about this mIsBuilt = true; } //----------------------------------------------------------------------------- } {CODE} That's all folks. --((User:Steven|Steven)) 04:32, 2 April 2009 (UTC) --- Alias: (alias(Geometry_Batching))
Search by Tags
Search Wiki by Freetags
Latest Changes
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
MOGRE Editable Terrain Manager
...more
Search
Find
Advanced
Search Help
Online Users
35 online users