void readLibraryGeometries(TiXmlDocument& doc, btAlignedObjectArray<GLInstanceGraphicsShape>& visualShapes, btHashMap<btHashString,int>& name2Shape, float extraScaling) { btHashMap<btHashString,TiXmlElement* > allSources; btHashMap<btHashString,VertexSource> vertexSources; for(TiXmlElement* geometry = doc.RootElement()->FirstChildElement("library_geometries")->FirstChildElement("geometry"); geometry != NULL; geometry = geometry->NextSiblingElement("geometry")) { btAlignedObjectArray<btVector3> vertexPositions; btAlignedObjectArray<btVector3> vertexNormals; btAlignedObjectArray<int> indices; const char* geometryName = geometry->Attribute("id"); for (TiXmlElement* mesh = geometry->FirstChildElement("mesh");(mesh != NULL); mesh = mesh->NextSiblingElement("mesh")) { TiXmlElement* vertices2 = mesh->FirstChildElement("vertices"); for (TiXmlElement* source = mesh->FirstChildElement("source");source != NULL;source = source->NextSiblingElement("source")) { const char* srcId= source->Attribute("id"); // printf("source id=%s\n",srcId); allSources.insert(srcId,source); } const char* vertexId = vertices2->Attribute("id"); //printf("vertices id=%s\n",vertexId); VertexSource vs; for(TiXmlElement* input = vertices2->FirstChildElement("input");input != NULL;input = input->NextSiblingElement("input")) { const char* sem = input->Attribute("semantic"); std::string semName(sem); // printf("sem=%s\n",sem); const char* src = input->Attribute("source"); // printf("src=%s\n",src); const char* srcIdRef = input->Attribute("source"); std::string source_name; source_name = std::string(srcIdRef); source_name = source_name.erase(0, 1); if (semName=="POSITION") { vs.m_positionArrayId = source_name; } if (semName=="NORMAL") { vs.m_normalArrayId = source_name; } } vertexSources.insert(vertexId,vs); for (TiXmlElement* primitive = mesh->FirstChildElement("triangles"); primitive; primitive = primitive->NextSiblingElement("triangles")) { std::string positionSourceName; std::string normalSourceName; int primitiveCount; primitive->QueryIntAttribute("count", &primitiveCount); bool positionAndNormalInVertex=false; int indexStride=1; int posOffset = 0; int normalOffset = 0; int numIndices = 0; { for (TiXmlElement* input = primitive->FirstChildElement("input");input != NULL;input = input->NextSiblingElement("input")) { const char* sem = input->Attribute("semantic"); std::string semName(sem); int offset = atoi(input->Attribute("offset")); if ((offset+1)>indexStride) indexStride=offset+1; //printf("sem=%s\n",sem); const char* src = input->Attribute("source"); //printf("src=%s\n",src); const char* srcIdRef = input->Attribute("source"); std::string source_name; source_name = std::string(srcIdRef); source_name = source_name.erase(0, 1); if (semName=="VERTEX") { //now we have POSITION and possibly NORMAL too, using same index array (<p>) VertexSource* vs = vertexSources[source_name.c_str()]; if (vs->m_positionArrayId.length()) { positionSourceName = vs->m_positionArrayId; posOffset = offset; } if (vs->m_normalArrayId.length()) { normalSourceName = vs->m_normalArrayId; normalOffset = offset; positionAndNormalInVertex = true; } } if (semName=="NORMAL") { btAssert(normalSourceName.length()==0); normalSourceName = source_name; normalOffset = offset; positionAndNormalInVertex = false; } } numIndices = primitiveCount * 3; } btAlignedObjectArray<float> positionFloatArray; int posStride=1; TiXmlElement** sourcePtr = allSources[positionSourceName.c_str()]; if (sourcePtr) { readFloatArray(*sourcePtr,positionFloatArray, posStride); } btAlignedObjectArray<float> normalFloatArray; int normalStride=1; sourcePtr = allSources[normalSourceName.c_str()]; if (sourcePtr) { readFloatArray(*sourcePtr,normalFloatArray,normalStride); } btAlignedObjectArray<int> curIndices; curIndices.reserve(numIndices*indexStride); TokenIntArray adder(curIndices); tokenize(primitive->FirstChildElement("p")->GetText(),adder); assert(curIndices.size() == numIndices*indexStride); int indexOffset = vertexPositions.size(); for(int index=0; index<numIndices; index++) { int posIndex = curIndices[index*indexStride+posOffset]; int normalIndex = curIndices[index*indexStride+normalOffset]; vertexPositions.push_back(btVector3(extraScaling*positionFloatArray[posIndex*3+0], extraScaling*positionFloatArray[posIndex*3+1], extraScaling*positionFloatArray[posIndex*3+2])); if (normalFloatArray.size() && (normalFloatArray.size()>normalIndex)) { vertexNormals.push_back(btVector3(normalFloatArray[normalIndex*3+0], normalFloatArray[normalIndex*3+1], normalFloatArray[normalIndex*3+2])); } else { //add a dummy normal of length zero, so it is easy to detect that it is an invalid normal vertexNormals.push_back(btVector3(0,0,0)); } } int curNumIndices = indices.size(); indices.resize(curNumIndices+numIndices); for(int index=0; index<numIndices; index++) { indices[curNumIndices+index] = index+indexOffset; } }//if(primitive != NULL) }//for each mesh int shapeIndex = visualShapes.size(); GLInstanceGraphicsShape& visualShape = visualShapes.expand(); { visualShape.m_vertices = new b3AlignedObjectArray<GLInstanceVertex>; visualShape.m_indices = new b3AlignedObjectArray<int>; int indexBase = 0; btAssert(vertexNormals.size()==vertexPositions.size()); for (int v=0;v<vertexPositions.size();v++) { GLInstanceVertex vtx; vtx.xyzw[0] = vertexPositions[v].x(); vtx.xyzw[1] = vertexPositions[v].y(); vtx.xyzw[2] = vertexPositions[v].z(); vtx.xyzw[3] = 1.f; vtx.normal[0] = vertexNormals[v].x(); vtx.normal[1] = vertexNormals[v].y(); vtx.normal[2] = vertexNormals[v].z(); vtx.uv[0] = 0.5f; vtx.uv[1] = 0.5f; visualShape.m_vertices->push_back(vtx); } for (int index=0;index<indices.size();index++) { visualShape.m_indices->push_back(indices[index]+indexBase); } printf(" index_count =%dand vertexPositions.size=%d\n",indices.size(), vertexPositions.size()); indexBase=visualShape.m_vertices->size(); visualShape.m_numIndices = visualShape.m_indices->size(); visualShape.m_numvertices = visualShape.m_vertices->size(); } printf("geometry name=%s\n",geometryName); name2Shape.insert(geometryName,shapeIndex); }//for each geometry }
QVector<VertexInputAttribute> CommonPipelineState::GetVertexInputs() { if(LogLoaded()) { if(IsLogD3D11()) { uint32_t byteOffs[128] = {}; auto &layouts = m_D3D11->m_IA.layouts; QVector<VertexInputAttribute> ret(layouts.count); for(int i = 0; i < layouts.count; i++) { QString semName(layouts[i].SemanticName); bool needsSemanticIdx = false; for(int j = 0; j < layouts.count; j++) { if(i != j && !semName.compare(QString(layouts[j].SemanticName), Qt::CaseInsensitive)) { needsSemanticIdx = true; break; } } uint32_t offs = layouts[i].ByteOffset; if(offs == UINT32_MAX) // APPEND_ALIGNED offs = byteOffs[layouts[i].InputSlot]; else byteOffs[layouts[i].InputSlot] = offs = layouts[i].ByteOffset; byteOffs[layouts[i].InputSlot] += layouts[i].Format.compByteWidth * layouts[i].Format.compCount; ret[i].Name = semName + (needsSemanticIdx ? QString::number(layouts[i].SemanticIndex) : ""); ret[i].VertexBuffer = (int)layouts[i].InputSlot; ret[i].RelativeByteOffset = offs; ret[i].PerInstance = layouts[i].PerInstance; ret[i].InstanceRate = (int)layouts[i].InstanceDataStepRate; ret[i].Format = layouts[i].Format; memset(&ret[i].GenericValue, 0, sizeof(PixelValue)); ret[i].Used = false; if(m_D3D11->m_IA.Bytecode != NULL) { rdctype::array<SigParameter> &sig = m_D3D11->m_IA.Bytecode->InputSig; for(int ia = 0; ia < sig.count; ia++) { if(!semName.compare(QString(sig[ia].semanticName), Qt::CaseInsensitive) && sig[ia].semanticIndex == layouts[i].SemanticIndex) { ret[i].Used = true; break; } } } } return ret; } else if(IsLogD3D12()) { uint32_t byteOffs[128] = {}; auto &layouts = m_D3D12->m_IA.layouts; QVector<VertexInputAttribute> ret(layouts.count); for(int i = 0; i < layouts.count; i++) { QString semName(layouts[i].SemanticName); bool needsSemanticIdx = false; for(int j = 0; j < layouts.count; j++) { if(i != j && !semName.compare(QString(layouts[j].SemanticName), Qt::CaseInsensitive)) { needsSemanticIdx = true; break; } } uint32_t offs = layouts[i].ByteOffset; if(offs == UINT32_MAX) // APPEND_ALIGNED offs = byteOffs[layouts[i].InputSlot]; else byteOffs[layouts[i].InputSlot] = offs = layouts[i].ByteOffset; byteOffs[layouts[i].InputSlot] += layouts[i].Format.compByteWidth * layouts[i].Format.compCount; ret[i].Name = semName + (needsSemanticIdx ? QString::number(layouts[i].SemanticIndex) : ""); ret[i].VertexBuffer = (int)layouts[i].InputSlot; ret[i].RelativeByteOffset = offs; ret[i].PerInstance = layouts[i].PerInstance; ret[i].InstanceRate = (int)layouts[i].InstanceDataStepRate; ret[i].Format = layouts[i].Format; memset(&ret[i].GenericValue, 0, sizeof(PixelValue)); ret[i].Used = false; if(m_D3D12->m_VS.ShaderDetails != NULL) { rdctype::array<SigParameter> &sig = m_D3D12->m_VS.ShaderDetails->InputSig; for(int ia = 0; ia < sig.count; ia++) { if(!semName.compare(QString(sig[ia].semanticName), Qt::CaseInsensitive) && sig[ia].semanticIndex == layouts[i].SemanticIndex) { ret[i].Used = true; break; } } } } return ret; } else if(IsLogGL()) { auto &attrs = m_GL->m_VtxIn.attributes; int num = 0; for(int i = 0; i < attrs.count; i++) { int attrib = -1; if(m_GL->m_VS.ShaderDetails != NULL) attrib = m_GL->m_VS.BindpointMapping.InputAttributes[i]; else attrib = i; if(attrib >= 0) num++; } int a = 0; QVector<VertexInputAttribute> ret(attrs.count); for(int i = 0; i < attrs.count && a < num; i++) { ret[a].Name = QString("attr%1").arg(i); memset(&ret[a].GenericValue, 0, sizeof(PixelValue)); ret[a].VertexBuffer = (int)attrs[i].BufferSlot; ret[a].RelativeByteOffset = attrs[i].RelativeOffset; ret[a].PerInstance = m_GL->m_VtxIn.vbuffers[attrs[i].BufferSlot].Divisor > 0; ret[a].InstanceRate = (int)m_GL->m_VtxIn.vbuffers[attrs[i].BufferSlot].Divisor; ret[a].Format = attrs[i].Format; ret[a].Used = true; if(m_GL->m_VS.ShaderDetails != NULL) { int attrib = m_GL->m_VS.BindpointMapping.InputAttributes[i]; if(attrib >= 0 && attrib < m_GL->m_VS.ShaderDetails->InputSig.count) ret[a].Name = m_GL->m_VS.ShaderDetails->InputSig[attrib].varName; if(attrib == -1) continue; if(!attrs[i].Enabled) { uint32_t compCount = m_GL->m_VS.ShaderDetails->InputSig[attrib].compCount; FormatComponentType compType = m_GL->m_VS.ShaderDetails->InputSig[attrib].compType; for(uint32_t c = 0; c < compCount; c++) { if(compType == eCompType_Float) ret[a].GenericValue.value_f[c] = attrs[i].GenericValue.f[c]; else if(compType == eCompType_UInt) ret[a].GenericValue.value_u[c] = attrs[i].GenericValue.u[c]; else if(compType == eCompType_SInt) ret[a].GenericValue.value_i[c] = attrs[i].GenericValue.i[c]; else if(compType == eCompType_UScaled) ret[a].GenericValue.value_f[c] = (float)attrs[i].GenericValue.u[c]; else if(compType == eCompType_SScaled) ret[a].GenericValue.value_f[c] = (float)attrs[i].GenericValue.i[c]; } ret[a].PerInstance = false; ret[a].InstanceRate = 0; ret[a].Format.compByteWidth = 4; ret[a].Format.compCount = compCount; ret[a].Format.compType = compType; ret[a].Format.special = false; ret[a].Format.srgbCorrected = false; } } a++; } return ret; } else if(IsLogVK()) { auto &attrs = m_Vulkan->VI.attrs; int num = 0; for(int i = 0; i < attrs.count; i++) { int attrib = -1; if(m_Vulkan->VS.ShaderDetails != NULL) { if(attrs[i].location < (uint32_t)m_Vulkan->VS.BindpointMapping.InputAttributes.count) attrib = m_Vulkan->VS.BindpointMapping.InputAttributes[attrs[i].location]; } else attrib = i; if(attrib >= 0) num++; } int a = 0; QVector<VertexInputAttribute> ret(num); for(int i = 0; i < attrs.count && a < num; i++) { ret[a].Name = QString("attr%1").arg(i); memset(&ret[a].GenericValue, 0, sizeof(PixelValue)); ret[a].VertexBuffer = (int)attrs[i].binding; ret[a].RelativeByteOffset = attrs[i].byteoffset; ret[a].PerInstance = false; if(attrs[i].binding < (uint32_t)m_Vulkan->VI.binds.count) ret[a].PerInstance = m_Vulkan->VI.binds[attrs[i].binding].perInstance; ret[a].InstanceRate = 1; ret[a].Format = attrs[i].format; ret[a].Used = true; if(m_Vulkan->VS.ShaderDetails != NULL) { int attrib = -1; if(attrs[i].location < (uint32_t)m_Vulkan->VS.BindpointMapping.InputAttributes.count) attrib = m_Vulkan->VS.BindpointMapping.InputAttributes[attrs[i].location]; if(attrib >= 0 && attrib < m_Vulkan->VS.ShaderDetails->InputSig.count) ret[a].Name = m_Vulkan->VS.ShaderDetails->InputSig[attrib].varName; if(attrib == -1) continue; } a++; } return ret; } } return QVector<VertexInputAttribute>(); }