void CopyVertex(PolygonGroup *srcGroup, uint32 srcPos, PolygonGroup *dstGroup, uint32 dstPos) { int32 srcFormat = srcGroup->GetFormat(); int32 dstFormat = dstGroup->GetFormat(); int32 copyFormat = srcFormat&dstFormat; //most common format; uint8 *srcData = srcGroup->meshData+srcPos*GetVertexSize(srcFormat); uint8 *dstData = dstGroup->meshData+dstPos*GetVertexSize(dstFormat); for (uint32 mask = EVF_LOWER_BIT; mask <= EVF_HIGHER_BIT; mask = mask << 1) { int32 vertexAttribSize = GetVertexSize(mask); if (mask©Format) Memcpy(dstData, srcData, vertexAttribSize); if (mask&srcFormat) srcData+=vertexAttribSize; if (mask&dstFormat) dstData+=vertexAttribSize; copyFormat&=~mask; } /*unsupported stream*/ DVASSERT((copyFormat == 0)&&"Unsupported attribute stream in copy"); }
int32 PolygonGroup::OptimazeVertexes(const uint8 * meshData, Vector<uint8> & optMeshData, uint32 vertexFormat) const { uint32 optimizedVertexCount = optMeshData.size() / GetVertexSize(vertexFormat); for (uint32 i = 0; i < optimizedVertexCount; ++i) { const float32 * optData = (float32*)(&optMeshData[i * GetVertexSize(vertexFormat)]); const float32 * tmpMeshData = (float32*) meshData; bool skip = false; for (uint32 mask = EVF_LOWER_BIT; mask <= EVF_HIGHER_BIT; mask = mask << 1) { if (!IsFloatDataEqual(&tmpMeshData, &optData, vertexFormat, mask)) { skip = true; break; } } if (skip) continue; return i; } optMeshData.resize(GetVertexSize(vertexFormat) * (optimizedVertexCount + 1)); uint8* dest = &optMeshData[GetVertexSize(vertexFormat) * optimizedVertexCount]; memcpy(dest, meshData, GetVertexSize(vertexFormat)); return optimizedVertexCount; }
void PolygonGroup::Load(KeyedArchive * keyedArchive, SceneFileV2 * sceneFile) { DataNode::Load(keyedArchive, sceneFile); vertexFormat = keyedArchive->GetInt32("vertexFormat"); vertexStride = GetVertexSize(vertexFormat); vertexCount = keyedArchive->GetInt32("vertexCount"); indexCount = keyedArchive->GetInt32("indexCount"); textureCoordCount = keyedArchive->GetInt32("textureCoordCount"); primitiveType = (ePrimitiveType)keyedArchive->GetInt32("primitiveType"); cubeTextureCoordCount = keyedArchive->GetInt32("cubeTextureCoordCount"); int32 formatPacking = keyedArchive->GetInt32("packing"); if (formatPacking == PACKING_NONE) { int size = keyedArchive->GetByteArraySize("vertices"); if (size != vertexCount * vertexStride) { Logger::Error("PolygonGroup::Load - Something is going wrong, size of vertex array is incorrect"); return; } SafeDeleteArray(meshData); meshData = new uint8[vertexCount * vertexStride]; const uint8 * archiveData = keyedArchive->GetByteArray("vertices"); memcpy(meshData, archiveData, size); } indexFormat = keyedArchive->GetInt32("indexFormat"); if (indexFormat == EIF_16) { int size = keyedArchive->GetByteArraySize("indices"); if (size != indexCount * INDEX_FORMAT_SIZE[indexFormat]) { Logger::Error("PolygonGroup::Load - Something is going wrong, size of index array is incorrect"); return; } SafeDeleteArray(indexArray); indexArray = new int16[indexCount]; const uint8 * archiveData = keyedArchive->GetByteArray("indices"); memcpy(indexArray, archiveData, indexCount * INDEX_FORMAT_SIZE[indexFormat]); } SafeDeleteArray(textureCoordArray); textureCoordArray = new Vector2*[textureCoordCount]; SafeDeleteArray(cubeTextureCoordArray); if(cubeTextureCoordCount) { cubeTextureCoordArray = new Vector3*[cubeTextureCoordCount]; } SafeRelease(renderDataObject); renderDataObject = new RenderDataObject(); UpdateDataPointersAndStreams(); RecalcAABBox(); BuildBuffers(); }
//-------------------------------------------------------------------------------- void VertexBuffer_DX11::Bind() const { Renderer_DX11* pDX11Renderer = (Renderer_DX11*)GetOwner(); u32 stride = GetVertexSize(); u32 offset = 0; pDX11Renderer->GetContext()->IASetVertexBuffers(0, 1, &m_pD3D11VertexBuffer, &stride, &offset); pDX11Renderer->GetContext()->IASetPrimitiveTopology(GetD3DPrimitiveTopology()); }
void PolygonGroup::OptimizeVertices(uint32 newVertexFormat, float32 eplison) { int32 newVertexStride = GetVertexSize(newVertexFormat); uint8 * newMeshData = new uint8[newVertexStride * vertexCount]; memset(newMeshData, 0, sizeof(newVertexStride * vertexCount)); uint8 * tmpMesh = meshData; uint8 * tmpNewMesh = newMeshData; for (int32 i = 0; i < vertexCount; ++i) { for (uint32 mask = EVF_LOWER_BIT; mask <= EVF_HIGHER_BIT; mask = mask << 1) { CopyData(&tmpMesh, &tmpNewMesh, vertexFormat, newVertexFormat, mask); } } Vector<uint8> optMeshData; tmpNewMesh = newMeshData; for (int32 i = 0; i < vertexCount; ++i) { int16 newIndex = OptimazeVertexes(tmpNewMesh, optMeshData, newVertexFormat); tmpNewMesh += GetVertexSize(newVertexFormat); for (int32 i1 = 0; i1 < indexCount; ++i1) { if (indexArray[i1] == i) indexArray[i1] = newIndex; } } uint32 newVertexCount = optMeshData.size() / GetVertexSize(newVertexFormat); SAFE_DELETE_ARRAY(meshData); SAFE_DELETE_ARRAY(newMeshData); vertexCount = newVertexCount; vertexStride = newVertexStride; vertexFormat = newVertexFormat; meshData = new uint8[vertexStride * vertexCount]; memcpy(meshData, &optMeshData[0], vertexStride * vertexCount); };
void PolygonGroup::CopyData(uint8 ** meshData, uint8 ** newMeshData, uint32 vertexFormat, uint32 newVertexFormat, uint32 format) const { if (vertexFormat & format) { uint32 formatSize = GetVertexSize(format); if (newVertexFormat & format) { memcpy(*newMeshData, *meshData, formatSize); *newMeshData += formatSize; } *meshData += formatSize; } }
bool PolygonGroup::IsFloatDataEqual(const float32 ** meshData, const float32 ** optData, uint32 vertexFormat, uint32 format) const { if (vertexFormat & format) { uint32 size = GetVertexSize(format); uint32 count = size / sizeof(float32); for (uint32 i = 0; i < count; ++i) { float32 x1 = **meshData; *meshData += sizeof(float32); float32 x2 = **optData; *optData += sizeof(float32); if (!FLOAT_EQUAL_EPS(x1, x2, 0.00001f)) return false; } } return true; }
void PolygonGroup::AllocateData(int32 _meshFormat, int32 _vertexCount, int32 _indexCount) { vertexCount = _vertexCount; indexCount = _indexCount; vertexStride = GetVertexSize(_meshFormat); vertexFormat = _meshFormat; textureCoordCount = GetTexCoordCount(vertexFormat); cubeTextureCoordCount = GetCubeTexCoordCount(vertexFormat); meshData = new uint8[vertexStride * vertexCount]; indexArray = new int16[indexCount]; textureCoordArray = new Vector2*[textureCoordCount]; cubeTextureCoordArray = new Vector3*[cubeTextureCoordCount]; renderDataObject = new RenderDataObject(); UpdateDataPointersAndStreams(); }
void VertexBuffer::BuildVBO() { GLDEBUG(); vector<VertexAttribute> attribs = GetAttributes(); int total_size = GetVertexSize(); InvalidateVBO(); // just in case... // generate a vbo glGenBuffers(1, &vbo_id); glBindBuffer(GL_ARRAY_BUFFER, vbo_id); // set the total size (based on the value we computed earlier) glBufferData(GL_ARRAY_BUFFER, total_size * num_verts, NULL, GL_STATIC_DRAW); int offset = 0; for(unsigned int i = 0; i < attribs.size(); ++i) { VertexAttribute attrib = attribs[i]; int attrib_size = 0; if(attrib.type == Float) attrib_size = sizeof(float) * attrib.n_per_vertex; if(attrib_size > 0) { if(attrib.type == Float) glBufferSubData(GL_ARRAY_BUFFER, offset * num_verts, attrib_size * num_verts, attribute_data[attrib.name].floats); offset += attrib_size; } } glBindBuffer(GL_ARRAY_BUFFER, 0); // don't leave hardware vbo on GLDEBUG(); }
void wish_mesh::CalculateBounds() { if (NumVertices > 0) { Bounds.min = v3(1000000); Bounds.max = v3(-1000000); u32 vSize = GetVertexSize(MeshType); u8* offset = (u8*)Vertices; v3* position = (v3*)offset; for (u32 i = 0; i < NumVertices; i++) { position = (v3*)offset; if (position->x < Bounds.min.x) { Bounds.min.x = position->x; } if (position->x > Bounds.max.x) { Bounds.max.x = position->x; } if (position->y < Bounds.min.y) { Bounds.min.y = position->y; } if (position->y > Bounds.max.y) { Bounds.max.y = position->y; } if (position->z < Bounds.min.z) { Bounds.min.z = position->z; } if (position->z > Bounds.max.z) { Bounds.max.z = position->z; } offset += vSize; } } else { Bounds.min = v3(0); Bounds.max = v3(0); } }
//-------------------------------------------------------------------------------- void VertexBuffer_DX11::Init(const void* in_pData) { //If buffer is constant, it needs to be initialized with data. AssertMsg(!(m_uiBufferType & eUT_Constant && in_pData == nullptr), L("Constant Buffers need to be initialized with data.")); AssertMsg(!(m_uiBufferType & eUT_Constant && m_uiVertexCount == 0), L("Constant Buffers need to be initialized with data.")); //If buffer is not CPU writable, it needs to be initialized with data. (at least until GPU write support/use) AssertMsg(!(!(m_uiBufferType & eUT_CPU_Writable) && in_pData == nullptr), L("Non-CPU Writable Buffers need to be initialized with data.")); AssertMsg(!(!(m_uiBufferType & eUT_CPU_Writable) && m_uiVertexCount == 0), L("Non-CPU Writable Buffers need to be initialized with data.")); if (GetVertexCount() == 0) return; Renderer_DX11* pDX11Renderer = (Renderer_DX11*)GetOwner(); D3D11_BUFFER_DESC vertexBufferDesc; vertexBufferDesc.ByteWidth = GetVertexCount() * GetVertexSize(); vertexBufferDesc.Usage = GetD3D11Usage(m_uiBufferType); vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vertexBufferDesc.CPUAccessFlags = GetCPUAccessFlags(m_uiBufferType); vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA vertexBufferInitData; vertexBufferInitData.pSysMem = in_pData; vertexBufferInitData.SysMemPitch = 0; vertexBufferInitData.SysMemSlicePitch = 0; SAFE_RELEASE(m_pD3D11VertexBuffer); if(in_pData == nullptr) HResult hr = pDX11Renderer->GetDevice()->CreateBuffer(&vertexBufferDesc, nullptr, &m_pD3D11VertexBuffer); else HResult hr = pDX11Renderer->GetDevice()->CreateBuffer(&vertexBufferDesc, &vertexBufferInitData, &m_pD3D11VertexBuffer); SET_D3D11_OBJECT_NAME(m_pD3D11VertexBuffer); }
void VertexUpdateCommand::copy() { auto& buf = GetTemporaryBuffer(); if (m_ctx_vb.data_ptr) { auto format = GuessVertexFormat(m_points, m_normals, m_colors, m_uvs, m_tangents); auto vertex_size = GetVertexSize(format); buf.resize(vertex_size * m_num_points); Interleave(buf.data(), format, m_num_points, m_points, m_normals, m_colors, m_uvs, m_tangents); memcpy(m_ctx_vb.data_ptr, buf.data(), buf.size()); } if (m_ctx_ib.data_ptr && m_indices) { // Unity's mesh index is 16 bit // convert 32 bit indices -> 16 bit indices using index_t = uint16_t; buf.resize(sizeof(index_t) * m_num_indices); index_t *indices = (index_t*)buf.data(); for (size_t i = 0; i < m_num_indices; ++i) { indices[i] = (index_t)m_indices[i]; } memcpy(m_ctx_ib.data_ptr, buf.data(), buf.size()); } }
//-------------------------------------------------------------------------------- void GeometryDX11::LoadToBuffers( ID3D11Device* pDevice ) { // Check the size of the assembled vertices CalculateVertexSize(); // Load the vertex buffer first by calculating the required size unsigned int vertices_length = GetVertexSize() * GetVertexCount(); char* pBytes = new char[vertices_length]; for ( int j = 0; j < m_iVertexCount; j++ ) { int iElemOffset = 0; for ( int i = 0; i < m_vElements.count(); i++ ) { memcpy( pBytes + j * m_iVertexSize + iElemOffset, m_vElements[i]->GetPtr(j), m_vElements[i]->SizeInBytes() ); iElemOffset += m_vElements[i]->SizeInBytes(); } } D3D11_SUBRESOURCE_DATA data; data.pSysMem = reinterpret_cast<void*>( pBytes ); data.SysMemPitch = 0; data.SysMemSlicePitch = 0; D3D11_BUFFER_DESC vbuffer; vbuffer.ByteWidth = vertices_length; vbuffer.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbuffer.MiscFlags = 0; vbuffer.StructureByteStride = 0; vbuffer.Usage = D3D11_USAGE_IMMUTABLE; vbuffer.CPUAccessFlags = 0; vbuffer.StructureByteStride = 0; pDevice->CreateBuffer( &vbuffer, &data, &m_pVertexBuffer ); delete [] pBytes; // TODO: add error checking here! // Load the index buffer by calculating the required size // based on the number of indices. data.pSysMem = reinterpret_cast<void*>( &m_vIndices[0] ); data.SysMemPitch = 0; data.SysMemSlicePitch = 0; D3D11_BUFFER_DESC ibuffer; ibuffer.ByteWidth = sizeof( unsigned int ) * GetIndexCount(); ibuffer.BindFlags = D3D11_BIND_INDEX_BUFFER; ibuffer.MiscFlags = 0; ibuffer.StructureByteStride = 0; ibuffer.Usage = D3D11_USAGE_IMMUTABLE; ibuffer.CPUAccessFlags = 0; ibuffer.StructureByteStride = 0; pDevice->CreateBuffer( &ibuffer, &data, &m_pIndexBuffer ); //m_iIB = RendererDX11::Get()->CreateIndexBuffer( &ibuffer, &data ); }
void wish_mesh::SetVertices(r32* vertices, u32 numVertices) { Vertices = vertices; NumVertices = numVertices; VertexSize = GetVertexSize(MeshType); CalculateBounds(); }
void PolygonGroup::UpdateDataPointersAndStreams() { int32 baseShift = 0; if (vertexFormat & EVF_VERTEX) { vertexArray = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_VERTEX); renderDataObject->SetStream(EVF_VERTEX, TYPE_FLOAT, 3, vertexStride, vertexArray); } if (vertexFormat & EVF_NORMAL) { normalArray = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_NORMAL); renderDataObject->SetStream(EVF_NORMAL, TYPE_FLOAT, 3, vertexStride, normalArray); } if (vertexFormat & EVF_COLOR) { colorArray = reinterpret_cast<uint32*>(meshData + baseShift); baseShift += GetVertexSize(EVF_COLOR); renderDataObject->SetStream(EVF_COLOR, TYPE_UNSIGNED_BYTE, 4, vertexStride, colorArray); } if (vertexFormat & EVF_TEXCOORD0) { textureCoordArray[0] = reinterpret_cast<Vector2*>(meshData + baseShift); baseShift += GetVertexSize(EVF_TEXCOORD0); renderDataObject->SetStream(EVF_TEXCOORD0, TYPE_FLOAT, 2, vertexStride, textureCoordArray[0]); } if (vertexFormat & EVF_TEXCOORD1) { textureCoordArray[1] = reinterpret_cast<Vector2*>(meshData + baseShift); baseShift += GetVertexSize(EVF_TEXCOORD1); renderDataObject->SetStream(EVF_TEXCOORD1, TYPE_FLOAT, 2, vertexStride, textureCoordArray[1]); } if (vertexFormat & EVF_TEXCOORD2) { textureCoordArray[2] = reinterpret_cast<Vector2*>(meshData + baseShift); baseShift += GetVertexSize(EVF_TEXCOORD2); renderDataObject->SetStream(EVF_TEXCOORD2, TYPE_FLOAT, 2, vertexStride, textureCoordArray[2]); } if (vertexFormat & EVF_TEXCOORD3) { textureCoordArray[3] = reinterpret_cast<Vector2*>(meshData + baseShift); baseShift += GetVertexSize(EVF_TEXCOORD3); renderDataObject->SetStream(EVF_TEXCOORD3, TYPE_FLOAT, 2, vertexStride, textureCoordArray[3]); } if (vertexFormat & EVF_TANGENT) { tangentArray = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_TANGENT); renderDataObject->SetStream(EVF_TANGENT, TYPE_FLOAT, 3, vertexStride, tangentArray); } if (vertexFormat & EVF_BINORMAL) { binormalArray = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_BINORMAL); renderDataObject->SetStream(EVF_BINORMAL, TYPE_FLOAT, 3, vertexStride, binormalArray); } if (vertexFormat & EVF_JOINTWEIGHT) { jointIdxArray = reinterpret_cast<int32*>(meshData + baseShift); weightArray = reinterpret_cast<float32*>(meshData + baseShift + 4 * 4); baseShift += GetVertexSize(EVF_JOINTWEIGHT); SafeDeleteArray(jointCountArray); jointCountArray = new int32[vertexCount]; } if (vertexFormat & EVF_CUBETEXCOORD0) { cubeTextureCoordArray[0] = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_CUBETEXCOORD0); renderDataObject->SetStream(EVF_TEXCOORD0, TYPE_FLOAT, 3, vertexStride, cubeTextureCoordArray[0]); } if (vertexFormat & EVF_CUBETEXCOORD1) { cubeTextureCoordArray[1] = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_CUBETEXCOORD1); renderDataObject->SetStream(EVF_TEXCOORD1, TYPE_FLOAT, 3, vertexStride, cubeTextureCoordArray[1]); } if (vertexFormat & EVF_CUBETEXCOORD2) { cubeTextureCoordArray[2] = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_CUBETEXCOORD2); renderDataObject->SetStream(EVF_TEXCOORD2, TYPE_FLOAT, 3, vertexStride, cubeTextureCoordArray[2]); } if (vertexFormat & EVF_CUBETEXCOORD3) { cubeTextureCoordArray[3] = reinterpret_cast<Vector3*>(meshData + baseShift); baseShift += GetVertexSize(EVF_CUBETEXCOORD3); renderDataObject->SetStream(EVF_TEXCOORD3, TYPE_FLOAT, 3, vertexStride, cubeTextureCoordArray[3]); } }