MeshChunk* Mesh::createMeshChunk(const IntermediateMeshData& data, Mesh& mesh) { MeshChunk* newChunk = new MeshChunk(); newChunk->streamMask = 1; newChunk->indexCount = data.indices.size(); mesh.m_meshChunks.push_back(newChunk); // vertices bool hasNormal = (data.normal.size() > 0); bool hasTangent = (data.tangent.size() > 0); bool hasBitangent = (data.bitangent.size() > 0); bool hasUv0 = (data.uv0.size() > 0); bool hasUv1 = (data.uv1.size() > 0); bool hasUv2 = (data.uv2.size() > 0); // create vertex declaration if not already available if (!mesh.m_vertexDeclaration) { VertexDeclaration* vertexDecl = new VertexDeclaration(); uint32 offset = 0; const VertexElement& element = vertexDecl->add("Position", 0, VEF_FLOAT3, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); if (hasNormal) { const VertexElement& element = vertexDecl->add("Normal", 0, VEF_FLOAT3, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } if (hasTangent) { const VertexElement& element = vertexDecl->add("Tangent", 0, VEF_FLOAT3, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } if (hasBitangent) { const VertexElement& element = vertexDecl->add("Bitangent", 0, VEF_FLOAT3, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } if (hasUv0) { const VertexElement& element = vertexDecl->add("Texcoord", 0, VEF_FLOAT2, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } if (hasUv1) { const VertexElement& element = vertexDecl->add("Texcoord", 1, VEF_FLOAT2, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } if (hasUv2) { const VertexElement& element = vertexDecl->add("Texcoord", 2, VEF_FLOAT2, 0, offset, false); offset += VertexDeclaration::sizeOfElementType(element.format); } mesh.m_vertexDeclaration = vertexDecl; } newChunk->vertexSize = 0; for (uint32 elementIdx = 0; ; ++elementIdx) { const VertexElement* element = mesh.m_vertexDeclaration->getElement(elementIdx); if (!element) break; newChunk->vertexSize += VertexDeclaration::sizeOfElementType(element->format); } size_t bufferSize = newChunk->vertexSize * data.position.size(); void* buffer = malloc(bufferSize); float* dest = (float*)buffer; for (uint32 i = 0; i < data.position.size(); ++i) { *dest++ = data.position[i].x; *dest++ = data.position[i].y; *dest++ = data.position[i].z; if (hasNormal) { *dest++ = data.normal[i].x; *dest++ = data.normal[i].y; *dest++ = data.normal[i].z; } if (hasTangent) { *dest++ = data.tangent[i].x; *dest++ = data.tangent[i].y; *dest++ = data.tangent[i].z; } if (hasBitangent) { *dest++ = data.bitangent[i].x; *dest++ = data.bitangent[i].y; *dest++ = data.bitangent[i].z; } if (hasUv0) { *dest++ = data.uv0[i].x; *dest++ = data.uv0[i].y; } if (hasUv1) { *dest++ = data.uv1[i].x; *dest++ = data.uv1[i].y; } if (hasUv2) { *dest++ = data.uv2[i].x; *dest++ = data.uv2[i].y; } } D3D11_BUFFER_DESC desc = {0}; desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; desc.ByteWidth = bufferSize; desc.Usage = D3D11_USAGE_IMMUTABLE; D3D11_SUBRESOURCE_DATA initialData = {0}; initialData.pSysMem = buffer; VALIDATE(RENDER_DEVICE->CreateBuffer(&desc, &initialData, &newChunk->streams[0])); // indices bool use32BitIndices = data.position.size() > 0xffff; bufferSize = data.indices.size() * (use32BitIndices ? sizeof(uint32) : sizeof(uint16)); buffer = malloc(bufferSize); if (use32BitIndices) { memcpy(buffer, &data.indices[0], sizeof(uint32) * data.indices.size()); } else { uint16* dest = (uint16*)buffer; for (uint32 i = 0; i < data.indices.size(); ++i) *dest++ = (uint16)data.indices[i]; } desc.BindFlags = D3D11_BIND_INDEX_BUFFER; desc.ByteWidth = bufferSize; desc.Usage = D3D11_USAGE_IMMUTABLE; initialData.pSysMem = buffer; VALIDATE(RENDER_DEVICE->CreateBuffer(&desc, &initialData, &newChunk->indices)); free(buffer); return newChunk; }