void DiInstanceBatchHardware::SetupVertices( const DiSubMesh* baseSubMesh ) { mRemoveOwnVertexData = true; mVerticesNum = baseSubMesh->GetVerticeNum(); DiVertexElements elements = baseSubMesh->GetVertexElements(); int blendSource = RemoveBlendData(elements); mVertexDecl = Driver->CreateVertexDeclaration(); mVertexDecl->AddElements(elements); uint16 nextFreeStream = 0; if (blendSource != -1) nextFreeStream = (uint16)blendSource; else nextFreeStream = mVertexDecl->GetElements().GetStreams(); uint16 nextFreeUV = mVertexDecl->GetElements().GetNextFreeTexcoord(); if (nextFreeUV > 8-2) { DI_WARNING("No enough rooms for texcoords"); return; } mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,5); mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,6); mVertexDecl->AddElement(nextFreeStream, VERT_TYPE_FLOAT4, VERT_USAGE_TEXCOORD,7); mVertexDecl->Create(); DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator(); while (si.HasMoreElements()) { DiSubMesh::SourceData sd = si.GetNext(); if ((int)(sd.stream) == blendSource) { continue; } DiVertexBuffer* buf = Driver->CreateVertexBuffer(); uint32 size = sd.GetSize(); buf->SetStride(sd.stride); buf->Create(size,RU_WRITE_ONLY,sd.stream); buf->WriteData(0, size, sd.data); buf->SetInstanceState(SOURCE_INSTANCE_INDEX); buf->SetInstanceNum(mInstancesPerBatch); mSourceData.push_back(buf); } DiVertexBuffer* buf = Driver->CreateVertexBuffer(); uint32 stride = mVertexDecl->GetElements().GetStreamElementsSize(nextFreeStream); uint32 size = mInstancesPerBatch * stride ; buf->SetStride(stride); buf->Create(size, RU_WRITE_ONLY, nextFreeStream); buf->SetInstanceState(SOURCE_INSTANCE_DATA); mSourceData.push_back(buf); }
void DiInstanceBatchShader::SetupNoSkinned( const DiSubMesh* baseSubMesh ) { mVertexDecl = Driver->CreateVertexDeclaration(); mVertexDecl->AddElements(baseSubMesh->GetVertexElements()); mVertexDecl->AddElement(mVertexDecl->GetElements().GetStreams(),VERT_TYPE_UBYTE4,VERT_USAGE_BLENDINDICES,0); mVertexDecl->Create(); DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator(); while (si.HasMoreElements()) { DiSubMesh::SourceData sd = si.GetNext(); DiVertexBuffer* buf = Driver->CreateVertexBuffer(); uint32 size = sd.GetSize() * mInstancesPerBatch; buf->SetStride(sd.stride); buf->Create(size,RU_WRITE_ONLY,sd.stream); BYTE* data = (BYTE*)buf->Lock(0,size); for( size_t j=0; j < mInstancesPerBatch; ++j ) { memcpy(data + sd.GetSize()*j,sd.data,sd.GetSize()); } buf->Unlock(); mSourceData.push_back(buf); } uint16 lastStream = mVertexDecl->GetElements().GetStreams()-1; DiVertexBuffer* buf = Driver->CreateVertexBuffer(); uint32 stride = mVertexDecl->GetElements().GetStreamElementsSize(lastStream); uint32 size = baseSubMesh->GetVerticeNum() * stride * mInstancesPerBatch; buf->SetStride(stride); buf->Create(size, RU_WRITE_ONLY, lastStream); char* thisBuf = static_cast<char*>(buf->Lock(0,size)); for( size_t j=0; j < mInstancesPerBatch; ++j ) { for( size_t k=0; k<baseSubMesh->GetVerticeNum(); ++k ) { *thisBuf++ = mInstancesPerBatch - j - 1; *thisBuf++ = mInstancesPerBatch - j - 1; *thisBuf++ = mInstancesPerBatch - j - 1; *thisBuf++ = mInstancesPerBatch - j - 1; } } buf->Unlock(); mSourceData.push_back(buf); }
void DiInstanceBatchShader::SetupHardwareSkinned( const DiSubMesh* baseSubMesh ) { const size_t numBones = mMotionReference->GetSkeleton()->GetNumBones();//baseSubMesh->GetBlendIndexToBoneIndexMap().size(); m_usNumWorldMatrices = mInstancesPerBatch * numBones; DiVertexElements eles = baseSubMesh->GetVertexElements(); uint16 nextFreeUV = eles.GetNextFreeTexcoord(); if (nextFreeUV > 8-1) { DI_WARNING("No enough rooms of texcoord"); return; } uint16 blendstream = eles.GetTypeUsageAtStream(VERT_TYPE_UBYTE4,VERT_USAGE_BLENDINDICES); eles.AddElement(blendstream, VERT_TYPE_FLOAT1, VERT_USAGE_TEXCOORD, 7); //instanceID mVertexDecl = Driver->CreateVertexDeclaration(); mVertexDecl->AddElements(eles); mVertexDecl->Create(); DiSubMesh::SourceDataIterator si = baseSubMesh->GetSourceDataIterator(); while (si.HasMoreElements()) { DiSubMesh::SourceData sd = si.GetNext(); DiVertexElements& ves = const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements(); DiVertexElements::ElementsList elementlist = ves.GetElementsAtStream(sd.stream); DiVertexBuffer* buf = Driver->CreateVertexBuffer(); uint32 size = sd.GetSize() * mInstancesPerBatch; buf->SetStride(sd.stride); buf->Create(size, RU_WRITE_ONLY, sd.stream); BYTE* startBuf = (BYTE*)buf->Lock(0,size); BYTE* data = startBuf; BYTE* startSrcBuf = (BYTE*)sd.data; BYTE* dataSrc = startSrcBuf; for( size_t j=0; j < mInstancesPerBatch; ++j ) { dataSrc = startSrcBuf; for (uint32 v = 0; v < sd.numVertices; v++) { for (size_t ei = 0; ei < elementlist.size(); ei++) { if (elementlist[ei].Usage == VERT_USAGE_BLENDINDICES) { *(data + elementlist[ei].Offset + 0) = *(dataSrc + elementlist[ei].Offset + 0) + j * numBones; *(data + elementlist[ei].Offset + 1) = *(dataSrc + elementlist[ei].Offset + 1) + j * numBones; *(data + elementlist[ei].Offset + 2) = *(dataSrc + elementlist[ei].Offset + 2) + j * numBones; *(data + elementlist[ei].Offset + 3) = *(dataSrc + elementlist[ei].Offset + 3) + j * numBones; } else if (elementlist[ei].Usage == VERT_USAGE_TEXCOORD && elementlist[ei].UsageIndex == 7) { float* d = (float*)(data + elementlist[ei].Offset); *d = (float)(j*numBones); } else { memcpy(data + elementlist[ei].Offset,dataSrc + elementlist[ei].Offset, DiVertexElements::GetElementTypeSize(DiVertexType(elementlist[ei].Type))); } } data += const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements().GetStreamElementsSize(sd.stream); dataSrc += const_cast<DiSubMesh*>(baseSubMesh)->GetVertexElements().GetStreamElementsSize(sd.stream); } } buf->Unlock(); mSourceData.push_back(buf); } }
void DiFoliageLayerBatch::GenerateGrassQuad( const float *grassPositions, unsigned int grassCount ) { ReleaseVertexDeclaration(); ReleaseSourceData(); ReleaseIndexBuffer(); unsigned int quadCount; quadCount = grassCount; unsigned int maxUInt16 = std::numeric_limits<uint16>::max(); if(grassCount > maxUInt16) { return; } if(quadCount > maxUInt16) { return; } if (quadCount <= 0) { mVerticesNum = 0; mPrimitiveCount = 0; return; } mVerticesNum = 4 * quadCount; mPrimitiveCount = 2 * quadCount; mVertexDecl = Driver->CreateVertexDeclaration(); mVertexDecl->AddElement(0,VERT_TYPE_FLOAT3, VERT_USAGE_POSITION); mVertexDecl->AddElement(0,VERT_TYPE_FLOAT2, VERT_USAGE_TEXCOORD); mVertexDecl->Create(); uint32 vertSize = mVertexDecl->GetElements().GetStreamElementsSize(0); uint32 size = vertSize * mVerticesNum; DiVertexBuffer* vb = Driver->CreateVertexBuffer(); vb->Create(size); vb->SetStride(vertSize); mSourceData.push_back(vb); DiVec2 chunkPos = mParent->mParent->GetTerrainMap()->GetChunkCenterPos(mParent->mChunkID.x,mParent->mChunkID.y); float* pReal = static_cast<float*>(vb->Lock(0,size)); float rndWidth = mLayer->mDesc->mMaxWidth - mLayer->mDesc->mMinWidth; float rndHeight = mLayer->mDesc->mMaxHeight - mLayer->mDesc->mMinHeight; float minY = DiMath::POS_INFINITY, maxY = DiMath::NEG_INFINITY; const float *posPtr = grassPositions; for (uint16 i = 0; i < grassCount; ++i) { float x = *posPtr++; float z = *posPtr++; float rnd = *posPtr++; float halfScaleX = (mLayer->mDesc->mMinWidth + rndWidth * rnd) * 0.5f; float scaleY = (mLayer->mDesc->mMinHeight + rndHeight * rnd); float angle = *posPtr++; float xTrans = DiMath::Cos(angle) * halfScaleX; float zTrans = DiMath::Sin(angle) * halfScaleX; float x1 = x - xTrans, z1 = z - zTrans; float x2 = x + xTrans, z2 = z + zTrans; float height = 0; mParent->mParent->GetTerrainMap()->GetHeight(chunkPos.x+x,chunkPos.y+z,height); float y1 = height; float y2 = height; *pReal++ = float(x1); *pReal++ = float(y1 + scaleY); *pReal++ = float(z1); //pos *pReal++ = 0.f; *pReal++ = 0.f; //uv *pReal++ = float(x2); *pReal++ = float(y2 + scaleY); *pReal++ = float(z2); //pos *pReal++ = 1.f; *pReal++ = 0.f; //uv *pReal++ = float(x1); *pReal++ = float(y1); *pReal++ = float(z1); //pos *pReal++ = 0.f; *pReal++ = 1.f; //uv *pReal++ = float(x2); *pReal++ = float(y2); *pReal++ = float(z2); //pos *pReal++ = 1.f; *pReal++ = 1.f; //uv if (y1 < minY) { minY = y1; } if (y2 < minY) { minY = y2; } if (y1 + scaleY > maxY) { maxY = y1 + scaleY; } if (y2 + scaleY > maxY) { maxY = y2 + scaleY; } } vb->Unlock(); uint32 ibsize = 6 * quadCount * sizeof(uint16); mIndexBuffer = Driver->CreateIndexBuffer(); mIndexBuffer->Create(ibsize); uint16* pI = static_cast<uint16*>(mIndexBuffer->Lock(0,ibsize)); for (uint16 i = 0; i < quadCount; ++i) { uint16 offset = i * 4; *pI++ = 0 + offset; *pI++ = 2 + offset; *pI++ = 1 + offset; *pI++ = 1 + offset; *pI++ = 2 + offset; *pI++ = 3 + offset; } mIndexBuffer->Unlock(); }