void LineSegmentCollection::UpdateGPUVertexData() { if (defaultGPUVertexData != nullptr) { std::size_t numLineSegments = lineSegments.size(); std::size_t numVertices = numLineSegments * 2; defaultGPUVertexData->Bind(); defaultGPUVertexData->Buffer(numVertices, GL_STATIC_DRAW); if (numVertices > 0) { std::vector<GPUVertexDataStorage> vertData(numVertices); for (std::size_t lineSegmentIndex = 0, vertDataIndex = 0; lineSegmentIndex < numLineSegments; ++lineSegmentIndex) { for (std::size_t linePointIndex = 0; linePointIndex < 2; ++linePointIndex) { const FVector3& point = (linePointIndex == 0) ? lineSegments[lineSegmentIndex].segment.P1 : lineSegments[lineSegmentIndex].segment.P2; vertData[vertDataIndex].position[0] = static_cast<float>( point.x ); vertData[vertDataIndex].position[1] = static_cast<float>( point.y ); vertData[vertDataIndex].position[2] = static_cast<float>( point.z ); const Color& color = lineSegments[lineSegmentIndex].color; vertData[vertDataIndex].color[0] = color.r; vertData[vertDataIndex].color[1] = color.g; vertData[vertDataIndex].color[2] = color.b; vertData[vertDataIndex].color[3] = color.a; ++vertDataIndex; } } defaultGPUVertexData->BufferSub(0, numVertices, vertData.data()); } defaultGPUVertexData->transferInfo.sendPositions = true; defaultGPUVertexData->transferInfo.sendColors = true; defaultGPUVertexData->transferInfo.sendNormals = false; defaultGPUVertexData->transferInfo.sendTexCoords = false; defaultGPUVertexData->drawMode = GL_LINES; } }
void ModelLoader::CreateVertexBuffer( Vertex::VERTEX_TYPE type ) { aiMesh* mesh = scene->mMeshes[0]; UINT count = mesh->mNumVertices; aiVector3D* vertices = mesh->mVertices; /* The switch case looks like duplicated code. It is not. vertData is a different type in each and SetVertices() is a template. */ switch( type ) { case Vertex::BASIC_32: { std::vector<Vertex::Basic32> vertData( count ); aiVector3D* normals = mesh->mNormals; aiVector3D* texCoords = mesh->mTextureCoords[0]; for( UINT i = 0; i<count; ++i ) { UpdateExtents( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Pos = XMFLOAT3( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Normal = XMFLOAT3( normals[i].x, normals[i].y, normals[i].z ); vertData[i].Tex = XMFLOAT2( texCoords[i].x, texCoords[i].y ); } SetVertices( device, count, vertData.data() ); break; } case Vertex::POS_NORMAL_TEX_TAN: { aiVector3D* normals = mesh->mNormals; aiVector3D* texCoords = mesh->mTextureCoords[0]; aiVector3D* tangents = mesh->mTangents; std::vector<Vertex::PosNormalTexTan> vertData( count ); for( UINT i = 0; i<count; ++i ) { UpdateExtents( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Pos = XMFLOAT3( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Normal = XMFLOAT3( normals[i].x, normals[i].y, normals[i].z ); vertData[i].Tex = XMFLOAT2( texCoords[i].x, texCoords[i].y ); vertData[i].TangentU = XMFLOAT4( tangents[i].x, tangents[i].y, tangents[i].z, 0.f ); } SetVertices( device, count, vertData.data() ); break; } case Vertex::POS_NORMAL_TEX_TAN_SKINNED: { aiVector3D* normals = mesh->mNormals; aiVector3D* texCoords = mesh->mTextureCoords[0]; aiVector3D* tangents = mesh->mTangents; std::vector<Vertex::PosNormalTexTanSkinned> vertData( count ); for( UINT i = 0; i<count; ++i ) { UpdateExtents( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Pos = XMFLOAT3( vertices[i].x, vertices[i].y, vertices[i].z ); vertData[i].Normal = XMFLOAT3( normals[i].x, normals[i].y, normals[i].z ); vertData[i].Tex = XMFLOAT2( texCoords[i].x, texCoords[i].y ); vertData[i].TangentU = XMFLOAT4( tangents[i].x, tangents[i].y, tangents[i].z, 0.f ); } // Bone Data std::multimap<int, BoneWeight> vertexBoneWeight; for( unsigned int boneIndex = 0; boneIndex<mesh->mNumBones; ++boneIndex ) { auto bone = mesh->mBones[boneIndex]; for( int i = 0; i<bone->mNumWeights; ++i ) { auto boneWeight = BoneWeight( boneIndex, bone->mWeights[i].mWeight ); vertexBoneWeight.insert( std::pair<int, BoneWeight>( bone->mWeights[i].mVertexId, boneWeight ) ); } } for( UINT i = 0; i<count; ++i ) { BYTE boneIndices[4] = { 0, 0, 0, 0 }; float weights[4] = { 0, 0, 0, 0 }; int j = 0; auto itlow = vertexBoneWeight.lower_bound( i ); auto itup = vertexBoneWeight.upper_bound( i ); assert( itlow!=itup ); // every vertex should have some influence for( auto it = itlow; it!=itup; ++it ) { if( j>3 ) { assert( false ); // only 4 boes should influence one vertex break; } boneIndices[j] = it->second.boneIndex; weights[j] = it->second.weight; ++j; } vertData[i].BoneIndicies[0] = boneIndices[0]; vertData[i].BoneIndicies[1] = boneIndices[1]; vertData[i].BoneIndicies[2] = boneIndices[2]; vertData[i].BoneIndicies[3] = boneIndices[3]; vertData[i].Weights = XMFLOAT4( weights ); } SetVertices( device, count, vertData.data() ); break; } } }
void EntityLinkDecorator::render(Vbo& vbo, RenderContext& context) { if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayNone) return; const Model::EntityList& entities = map().entities(); if (entities.empty()) return; SetVboState activateVbo(vbo, Vbo::VboActive); if (m_doRebuild) { delete m_vertexArray; m_vertexArray = NULL; m_doRebuild = false; // for keeping track of which entities have already been visited by the link-gathering algorithm - should this be part of each entity instead ? Model::EntitySet visitedEntities; Vec4f::List vertsLocal; // links directly connected to a selected entity Vec4f::List vertsContext; // links not directly connected, but in the same context Vec4f::List vertsUnrelated; // links not related to the current selection Model::EntityList::const_iterator it, end; // first pass, outputs local or local+context links for (it = entities.begin(), end = entities.end(); it != end; ++it) { Model::Entity& entity = **it; if (entity.selected()) { if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayLocal) { gatherLinksLocal(vertsLocal, context, entity); } else { gatherLinks(vertsLocal, vertsContext, context, entity, visitedEntities); } } } // second pass, only used in "display all" mode, outputs target links of entities the first pass didn't visit if (context.viewOptions().linkDisplayMode() == View::ViewOptions::LinkDisplayAll) { Model::EntitySet::const_iterator vIt; for (it = entities.begin(), end = entities.end(); it != end; ++it) { Model::Entity& entity = **it; vIt = visitedEntities.lower_bound( &entity ); if( *vIt != &entity ) gatherLinksUnrelated(vertsUnrelated, context, entity); } } unsigned int vertexCount = static_cast<unsigned int>(vertsLocal.size() + vertsContext.size() + vertsUnrelated.size()); if (vertexCount == 0) return; //FIXME : doesn't need to be a color4f at the moment m_vertexArray = new VertexArray(vbo, GL_LINES, vertexCount, Attribute::position3f(), Attribute::color4f(), 0); SetVboState mapVbo(vbo, Vbo::VboMapped); // draw order : unrelated -> context -> local // vertData.y sets the type of link for the shader ( 0 = unrelated, 0.5 = context, 1.0 = local ) Vec4f vertData(1.0f); vertData.y = 0.0f; for (int i = 0; i != vertsUnrelated.size(); ++i ) { vertData.x = vertsUnrelated[i].w; m_vertexArray->addAttribute(Vec3f(vertsUnrelated[i].x, vertsUnrelated[i].y, vertsUnrelated[i].z)); m_vertexArray->addAttribute(vertData); } vertData.y = 0.5f; for (int i = 0; i != vertsContext.size(); ++i) { vertData.x = vertsContext[i].w; m_vertexArray->addAttribute(Vec3f(vertsContext[i].x, vertsContext[i].y, vertsContext[i].z)); m_vertexArray->addAttribute(vertData); } vertData.y = 1.0f; for (int i = 0; i != vertsLocal.size(); ++i) { vertData.x = vertsLocal[i].w; m_vertexArray->addAttribute(Vec3f(vertsLocal[i].x, vertsLocal[i].y, vertsLocal[i].z)); m_vertexArray->addAttribute(vertData); } m_valid = true; } if (!m_valid || m_vertexArray == NULL) return; ActivateShader shader(context.shaderManager(), Shaders::EntityLinkShader ); shader.currentShader().setUniformVariable("CameraPosition", context.camera().position()); //shader.currentShader().setUniformVariable("Color", m_color); // unused at the moment, make color view-prefs for the different types of links ? shader.currentShader().setUniformVariable("Occluded", 1.0f); // render the "occluded" portion without depth-test glLineWidth(2.0f); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); m_vertexArray->render(); shader.currentShader().setUniformVariable("Occluded", 0.0f); glEnable(GL_DEPTH_TEST); m_vertexArray->render(); glDepthMask(GL_TRUE); glLineWidth(1.0f); }