//-----------------------------------------------------------------------
	void InstanceBatchShader::setupHardwareSkinned( const SubMesh* baseSubMesh, VertexData *thisVertexData,
													VertexData *baseVertexData )
	{
		const size_t numBones = baseSubMesh->blendIndexToBoneIndexMap.size();
		mNumWorldMatrices = mInstancesPerBatch * numBones;

		for( size_t i=0; i<=thisVertexData->vertexDeclaration->getMaxSource(); ++i )
		{
			//Create our own vertex buffer
			HardwareVertexBufferSharedPtr vertexBuffer =
											HardwareBufferManager::getSingleton().createVertexBuffer(
											thisVertexData->vertexDeclaration->getVertexSize(i),
											thisVertexData->vertexCount,
											HardwareBuffer::HBU_STATIC_WRITE_ONLY );
			thisVertexData->vertexBufferBinding->setBinding( i, vertexBuffer );

			VertexDeclaration::VertexElementList veList =
											thisVertexData->vertexDeclaration->findElementsBySource(i);

			//Grab the base submesh data
			HardwareVertexBufferSharedPtr baseVertexBuffer =
													baseVertexData->vertexBufferBinding->getBuffer(i);

			char* thisBuf = static_cast<char*>(vertexBuffer->lock(HardwareBuffer::HBL_DISCARD));
			char* baseBuf = static_cast<char*>(baseVertexBuffer->lock(HardwareBuffer::HBL_READ_ONLY));
			char *startBuf = baseBuf;

			//Copy and repeat
			for( size_t j=0; j<mInstancesPerBatch; ++j )
			{
				//Repeat source
				baseBuf = startBuf;

				for( size_t k=0; k<baseVertexData->vertexCount; ++k )
				{
					VertexDeclaration::VertexElementList::const_iterator it = veList.begin();
					VertexDeclaration::VertexElementList::const_iterator en = veList.end();

					while( it != en )
					{
						switch( it->getSemantic() )
						{
						case VES_BLEND_INDICES:
						*(thisBuf + it->getOffset() + 0) = *(baseBuf + it->getOffset() + 0) + j * numBones;
						*(thisBuf + it->getOffset() + 1) = *(baseBuf + it->getOffset() + 1) + j * numBones;
						*(thisBuf + it->getOffset() + 2) = *(baseBuf + it->getOffset() + 2) + j * numBones;
						*(thisBuf + it->getOffset() + 3) = *(baseBuf + it->getOffset() + 3) + j * numBones;
							break;
						default:
							memcpy( thisBuf + it->getOffset(), baseBuf + it->getOffset(), it->getSize() );
							break;
						}
						++it;
					}
					thisBuf += baseVertexData->vertexDeclaration->getVertexSize(i);
					baseBuf += baseVertexData->vertexDeclaration->getVertexSize(i);
				}
			}

			baseVertexBuffer->unlock();
			vertexBuffer->unlock();
		}
	}
Example #2
0
	//---------------------------------------------------------------------
	bool OptimiseTool::calculateDuplicateVertices()
	{
		bool duplicates = false;

		// Lock all the buffers first
		typedef std::vector<char*> BufferLocks;
		BufferLocks bufferLocks;
		const VertexBufferBinding::VertexBufferBindingMap& bindings =
			mTargetVertexData->vertexBufferBinding->getBindings();
		VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi;
		bufferLocks.resize(mTargetVertexData->vertexBufferBinding->getLastBoundIndex()+1);
		for (bindi = bindings.begin(); bindi != bindings.end(); ++bindi)
		{
			char* lock = static_cast<char*>(bindi->second->lock(HardwareBuffer::HBL_READ_ONLY));
			bufferLocks[bindi->first] = lock;
		}

		for (uint32 v = 0; v < mTargetVertexData->vertexCount; ++v)
		{
			UniqueVertex uniqueVertex;
			const VertexDeclaration::VertexElementList& elemList =
				mTargetVertexData->vertexDeclaration->getElements();
			VertexDeclaration::VertexElementList::const_iterator elemi;
			unsigned short uvSets = 0;
			for (elemi = elemList.begin(); elemi != elemList.end(); ++elemi)
			{
				// all float pointers for the moment
				float *pFloat;
				elemi->baseVertexPointerToElement(
					bufferLocks[elemi->getSource()], &pFloat);

				switch(elemi->getSemantic())
				{
				case VES_POSITION:
					uniqueVertex.position.x = *pFloat++;
					uniqueVertex.position.y = *pFloat++;
					uniqueVertex.position.z = *pFloat++;
					break;
				case VES_NORMAL:
					uniqueVertex.normal.x = *pFloat++;
					uniqueVertex.normal.y = *pFloat++;
					uniqueVertex.normal.z = *pFloat++;
					break;
				case VES_TANGENT:
					uniqueVertex.tangent.x = *pFloat++;
					uniqueVertex.tangent.y = *pFloat++;
					uniqueVertex.tangent.z = *pFloat++;
					// support w-component on tangent if present
					if (VertexElement::getTypeCount(elemi->getType()) == 4)
					{
						uniqueVertex.tangent.w = *pFloat++;
					}
					break;
				case VES_BINORMAL:
					uniqueVertex.binormal.x = *pFloat++;
					uniqueVertex.binormal.y = *pFloat++;
					uniqueVertex.binormal.z = *pFloat++;
					break;
				case VES_TEXTURE_COORDINATES:
					// supports up to 4 dimensions
					for (unsigned short dim = 0;
						dim < VertexElement::getTypeCount(elemi->getType()); ++dim)
					{
						uniqueVertex.uv[elemi->getIndex()][dim] = *pFloat++;
					}
					++uvSets;
					break;
				case VES_BLEND_INDICES:
				case VES_BLEND_WEIGHTS:
				case VES_DIFFUSE:
				case VES_SPECULAR:
					// No action needed for these semantics.
					break;
				};
			}

			if (v == 0)
			{
				// set up comparator
				UniqueVertexLess lessObj;
				lessObj.pos_tolerance = mPosTolerance;
				lessObj.norm_tolerance = mNormTolerance;
				lessObj.uv_tolerance = mUVTolerance;
				lessObj.uvSets = uvSets;
				mUniqueVertexMap = UniqueVertexMap(lessObj);
			}

			// try to locate equivalent vertex in the list already
			uint32 indexUsed;
			UniqueVertexMap::iterator ui = mUniqueVertexMap.find(uniqueVertex);
			bool isOrig = false;
			if (ui != mUniqueVertexMap.end())
			{
				// re-use vertex, remap
				indexUsed = ui->second.newIndex;
				duplicates = true;
			}
			else
			{
				// new vertex
				isOrig = true;
				indexUsed = static_cast<uint32>(mUniqueVertexMap.size());
				// store the originating and new vertex index in the unique map
				VertexInfo newInfo(v, indexUsed);
				// lookup
				mUniqueVertexMap[uniqueVertex] = newInfo;
				// ordered
				mUniqueVertexList.push_back(newInfo);

			}
			// Insert remap entry (may map to itself)
			mIndexRemap.push_back(IndexInfo(indexUsed, isOrig));


			// increment buffer lock pointers
			for (bindi = bindings.begin(); bindi != bindings.end(); ++bindi)
			{
				bufferLocks[bindi->first] += bindi->second->getVertexSize();
			}

		}


		// unlock the buffers now
		for (bindi = bindings.begin(); bindi != bindings.end(); ++bindi)
		{
			bindi->second->unlock();
		}

		// Were there duplicates?
		return duplicates;

	}