void MyView::loadMeshes() { generateLightMeshes(); std::vector<SceneModel::Mesh> meshes = SceneModel::GeometryBuilder().getAllMeshes(); std::vector<SceneModel::Instance> instances = scene_->getAllInstances(); Mesh mesh; //for each mesh for (int i = 0; i < meshes.size(); i++) { std::vector<glm::vec3> positions = meshes[i].getPositionArray(); std::vector<glm::vec3> normals = meshes[i].getNormalArray(); std::vector<glm::vec2> texCoords = meshes[i].getTextureCoordinateArray(); std::vector<unsigned int> elements = meshes[i].getElementArray(); std::vector<vertex> vertexData; bool hasTexCoords = texCoords.size() > 0; for (int j = 0; j < positions.size(); j++) { vertex v; v.pos = positions[j]; v.normal = normals[j]; if (hasTexCoords) { v.texCoords = texCoords[j]; } else { //mesh has no tex coords... fill with 0s for now, refactor later v.texCoords = glm::vec2(0, 0); } vertexData.push_back(v); } glGenBuffers(1, &mesh.vertex_data_vbo); glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_data_vbo); glBufferData(GL_ARRAY_BUFFER, vertexData.size() * sizeof(vertex), vertexData.data(), GL_STATIC_DRAW); glGenBuffers(1, &mesh.element_vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.element_vbo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, elements.size() * sizeof(unsigned int), elements.data(), GL_STATIC_DRAW); mesh.element_count = elements.size(); glGenVertexArrays(1, &mesh.vao); glBindVertexArray(mesh.vao); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.element_vbo); glEnableVertexAttribArray(POSITION); glVertexAttribPointer(POSITION, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), TGL_BUFFER_OFFSET_OF(vertex, pos)); glEnableVertexAttribArray(NORMAL); glVertexAttribPointer(NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), TGL_BUFFER_OFFSET_OF(vertex, normal)); glEnableVertexAttribArray(TEX_COORD); glVertexAttribPointer(TEX_COORD, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), TGL_BUFFER_OFFSET_OF(vertex, texCoords)); glBindBuffer(GL_ARRAY_BUFFER, 0); std::vector<InstanceData> instancesData; mesh.instanceIDs.clear(); for (int x = 0; x < instances.size(); x++){ if (instances[x].getMeshId() == meshes[i].getId()){ InstanceData id; id.xForm = glm::mat4(instances[x].getTransformationMatrix()); id.matColour = (float)(instances[x].getMaterialId() - 200) + 0.5f; instancesData.push_back(id); mesh.instanceIDs.push_back(instances[x].getId()); } } int numInstances = instancesData.size(); GLsizei vec4Size = sizeof(glm::vec4); //instanced data glGenBuffers(1, &mesh.instance_data_vbo); glBindBuffer(GL_ARRAY_BUFFER, mesh.instance_data_vbo); glBufferData(GL_ARRAY_BUFFER, numInstances * sizeof(InstanceData), instancesData.data(), GL_STREAM_DRAW); glEnableVertexAttribArray(MATERIAL_COLOUR); glVertexAttribPointer(MATERIAL_COLOUR, 1, GL_FLOAT, GL_FALSE, sizeof(InstanceData), TGL_BUFFER_OFFSET_OF(InstanceData, matColour)); glVertexAttribDivisor(MATERIAL_COLOUR, 1); //mat4 needs to be passed as 4 lots of vec4s for (int n = 0; n < 4; n++){ glEnableVertexAttribArray(X_FORM + n); glVertexAttribPointer(X_FORM + n, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), TGL_BUFFER_OFFSET_OF(InstanceData, xForm) + (n * vec4Size)); glVertexAttribDivisor(X_FORM + n, 1); } glBindVertexArray(0); meshes_.push_back(mesh); } }
void MyView:: windowViewWillStart(std::shared_ptr<tygra::Window> window) { assert(scene_ != nullptr); ResetConsole(); /* Create and fill the vbos and vao in an interleaved manner from the scene data. Interleaving was chosen because the data would arrive to the gpu in a stream that would be in the order it would need for the shader and specific draw function to expect speeding up chache hits. The textures are also loaded on start so they can be assigned to maps and used in rendering the specific mesh using its material data. */ #pragma region SceneModel::GeometryBuilder builder; std::vector<Vertex> vertices; std::vector<unsigned int> elements; const auto& scene_meshes = builder.getAllMeshes(); for (const auto& scene_mesh : scene_meshes) { MeshGL& newMesh = meshes_[scene_mesh.getId()]; const auto& source_mesh = builder.getMeshById(scene_mesh.getId()); const auto& positions = source_mesh.getPositionArray(); const auto& elementsArr = source_mesh.getElementArray(); const auto& normals = source_mesh.getNormalArray(); const auto& tangents = source_mesh.getTangentArray(); const auto& text_coord = source_mesh.getTextureCoordinateArray(); newMesh.first_vertex_index = vertices.size(); vertices.reserve(vertices.size() + positions.size()); for (unsigned int i = 0; i < positions.size(); ++i) { Vertex vertex; vertex.position = positions[i]; vertex.normal = normals[i]; vertex.tangent = tangents[i]; vertex.texcoord = text_coord[i]; vertices.push_back(vertex); } newMesh.first_element_index = elements.size(); elements.insert(elements.end(), elementsArr.begin(), elementsArr.end()); newMesh.element_count = elementsArr.size(); } glGenBuffers(1, &vertex_vbo); glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), // size of data in bytes vertices.data(), // pointer to the data GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &element_vbo); glBindBuffer(GL_ARRAY_BUFFER, element_vbo); glBufferData(GL_ARRAY_BUFFER, elements.size() * sizeof(unsigned int), // size of data in bytes elements.data(), // pointer to the data GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenVertexArrays(1, &vao); glBindVertexArray(vao); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_vbo); glBindBuffer(GL_ARRAY_BUFFER, vertex_vbo); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), TGL_BUFFER_OFFSET_OF(Vertex, position)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), TGL_BUFFER_OFFSET_OF(Vertex, normal)); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), TGL_BUFFER_OFFSET_OF(Vertex, tangent)); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), TGL_BUFFER_OFFSET_OF(Vertex, texcoord)); // make nothing active (deactivate vbo and vao) glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); #pragma endregion //Load the mesh into buffers #pragma region //Load the textures into a map of handles LoadTexture("diff0.png"); LoadTexture("diff1.png"); LoadTexture("spec1.png"); LoadTexture("spec2.png"); //Create the light vector so there will be memory already reserved that can just be overwritten if values have been changed. This has been done on //start for effiences in the constant render loop function. for (unsigned int i = 0; i < scene_->getAllLights().size(); ++i) { Light light; light.position = scene_->getAllLights()[i].getPosition(); light.range = scene_->getAllLights()[i].getRange(); light.intensity = scene_->getAllLights()[i].getIntensity(); lights.push_back(light); } #pragma endregion // Textures and Lights }