//----------------------------------------------------------------------- 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(); } }
//--------------------------------------------------------------------- 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; }