QString ModelIndexer::findModel(const qmt::Uid &modelUid) { QMutexLocker locker(&d->indexerMutex); QSet<IndexedModel *> indexedModels = d->indexedModelsByUid.value(modelUid); if (indexedModels.isEmpty()) return QString(); IndexedModel *indexedModel = *indexedModels.cbegin(); QMT_ASSERT(indexedModel, return QString()); return indexedModel->file(); }
void TestGame::Init(const Window& window) { Material bricks("bricks", Texture("bricks.jpg"), 0.0f, 0, Texture("bricks_normal.jpg"), Texture("bricks_disp.png"), 0.03f, -0.5f); Material bricks2("bricks2", Texture("bricks2.jpg"), 0.0f, 0, Texture("bricks2_normal.png"), Texture("bricks2_disp.jpg"), 0.04f, -1.0f); //Material skin("humanFace", Texture("human.jpg"), 0.0f, 0, Texture("human_normal_inv.jpg")); //Material skin("humanFace", Texture("human.jpg"), 0.08f, 8, Texture("human_normal_inv.jpg")); IndexedModel square; { square.AddVertex(1.0f, -1.0f, 0.0f); square.AddTexCoord(Vector2f(1.0f, 1.0f)); square.AddVertex(1.0f, 1.0f, 0.0f); square.AddTexCoord(Vector2f(1.0f, 0.0f)); square.AddVertex(-1.0f, -1.0f, 0.0f); square.AddTexCoord(Vector2f(0.0f, 1.0f)); square.AddVertex(-1.0f, 1.0f, 0.0f); square.AddTexCoord(Vector2f(0.0f, 0.0f)); square.AddFace(0, 1, 2); square.AddFace(2, 1, 3); } Mesh customMesh("square", square.Finalize()); AddToScene((new Entity(Vector3f(0, -1, 5), Quaternion(), 32.0f)) ->AddComponent(new MeshRenderer(Mesh("terrain02.obj"), Material("bricks")))); AddToScene((new Entity(Vector3f(7,0,7))) ->AddComponent(new PointLight(Vector3f(0,1,0), 0.4f, Attenuation(0,0,1)))); AddToScene((new Entity(Vector3f(20,-11.0f,5), Quaternion(Vector3f(1,0,0), ToRadians(-60.0f)) * Quaternion(Vector3f(0,1,0), ToRadians(90.0f)))) ->AddComponent(new SpotLight(Vector3f(0,1,1), 0.4f, Attenuation(0,0,0.02f), ToRadians(91.1f), 7, 1.0f, 0.5f))); AddToScene((new Entity(Vector3f(), Quaternion(Vector3f(1,0,0), ToRadians(-45)))) ->AddComponent(new DirectionalLight(Vector3f(1,1,1), 0.4f, 10, 80.0f, 1.0f))); AddToScene((new Entity(Vector3f(0, 2, 0), Quaternion(Vector3f(0,1,0), 0.4f), 1.0f)) ->AddComponent(new MeshRenderer(Mesh("plane3.obj"), Material("bricks2"))) ->AddChild((new Entity(Vector3f(0, 0, 25))) ->AddComponent(new MeshRenderer(Mesh("plane3.obj"), Material("bricks2"))) ->AddChild((new Entity()) ->AddComponent(new CameraComponent(Matrix4f().InitPerspective(ToRadians(70.0f), window.GetAspect(), 0.1f, 1000.0f))) ->AddComponent(new FreeLook(window.GetCenter())) ->AddComponent(new FreeMove(10.0f))))); AddToScene((new Entity(Vector3f(24,-12,5), Quaternion(Vector3f(0,1,0), ToRadians(30.0f)))) ->AddComponent(new MeshRenderer(Mesh("sphere.obj"), Material("bricks")))); AddToScene((new Entity(Vector3f(0,0,7), Quaternion(), 1.0f)) ->AddComponent(new MeshRenderer(Mesh("square"), Material("bricks2")))); }
void ResourceManager::LoadMesh(const std::string& fileName, Mesh& mesh) { std::vector<std::string> splits; int split_length = 0; split_length = _split_string(fileName, std::string("."), splits); IndexedModel *model; if (splits[split_length - 1] == "obj") { model = new ObjModel(fileName); model->loadToMesh(&mesh); delete model; } else { throw ResourceException("Mesh loading for file type " + splits[split_length - 1] + " not implemented yet"); } }
void ModelIndexer::IndexerThread::onFilesQueued() { QMutexLocker locker(&m_indexer->d->indexerMutex); while (!m_indexer->d->filesQueue.isEmpty()) { ModelIndexer::QueuedFile queuedFile = m_indexer->d->filesQueue.takeFirst(); m_indexer->d->queuedFilesSet.remove(queuedFile); qCDebug(logger) << "handle queued file " << queuedFile.file() << "from project " << queuedFile.project()->displayName(); bool scanModel = false; IndexedModel *indexedModel = m_indexer->d->indexedModels.value(queuedFile.file()); if (!indexedModel) { qCDebug(logger) << "create new indexed model"; indexedModel = new IndexedModel(queuedFile.file(), queuedFile.lastModified()); indexedModel->addOwningProject(queuedFile.project()); m_indexer->d->indexedModels.insert(queuedFile.file(), indexedModel); scanModel = true; } else if (queuedFile.lastModified() > indexedModel->lastModified()) { qCDebug(logger) << "update indexed model"; indexedModel->addOwningProject(queuedFile.project()); indexedModel->reset(queuedFile.lastModified()); scanModel = true; } if (scanModel) { locker.unlock(); // load model file qmt::ProjectSerializer projectSerializer; qmt::Project project; try { projectSerializer.load(queuedFile.file(), &project); } catch (const qmt::Exception &e) { qWarning() << e.errorMessage(); return; } locker.relock(); indexedModel->setModelUid(project.uid()); // add indexedModel to set of indexedModelsByUid QSet<IndexedModel *> indexedModels = m_indexer->d->indexedModelsByUid.value(project.uid()); indexedModels.insert(indexedModel); m_indexer->d->indexedModelsByUid.insert(project.uid(), indexedModels); // collect all diagrams of model DiagramsCollectorVisitor visitor(indexedModel); project.rootPackage()->accept(&visitor); if (m_indexer->d->defaultModelFiles.contains(queuedFile)) { m_indexer->d->defaultModelFiles.remove(queuedFile); // check if model has a diagram which could be opened qmt::FindRootDiagramVisitor diagramVisitor; project.rootPackage()->accept(&diagramVisitor); if (diagramVisitor.diagram()) emit m_indexer->openDefaultModel(project.uid()); } } } }
void TestGame::init() { m_root.setEngine(m_engine); IndexedModel model = IndexedModel(); std::vector<Vertex> vertices; std::vector<unsigned int> indices; // vertices.push_back(Vertex(Vector3f(-1, -1, -1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f(-1, 1, -1), Vector2f(0, 0))); // vertices.push_back(Vertex(Vector3f( 1, 1, -1), Vector2f(0, 1))); // vertices.push_back(Vertex(Vector3f( 1, -1, -1), Vector2f(1, 1))); // // vertices.push_back(Vertex(Vector3f(-1, -1, 1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f(-1, 1, 1), Vector2f(0, 0))); // vertices.push_back(Vertex(Vector3f( 1, 1, 1), Vector2f(0, 1))); // vertices.push_back(Vertex(Vector3f( 1, -1, 1), Vector2f(1, 1))); // // vertices.push_back(Vertex(Vector3f(-1, -1, -1), Vector2f(0, 1))); // vertices.push_back(Vertex(Vector3f(-1, -1, 1), Vector2f(1, 1))); // vertices.push_back(Vertex(Vector3f( 1, -1, 1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f( 1, -1, -1), Vector2f(0, 0))); // // vertices.push_back(Vertex(Vector3f(-1, 1, -1), Vector2f(0, 1))); // vertices.push_back(Vertex(Vector3f(-1, 1, 1), Vector2f(1, 1))); // vertices.push_back(Vertex(Vector3f( 1, 1, 1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f( 1, 1, -1), Vector2f(0, 0))); // // vertices.push_back(Vertex(Vector3f(-1, -1, -1), Vector2f(1, 1))); // vertices.push_back(Vertex(Vector3f(-1, -1, 1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f(-1, 1, 1), Vector2f(0, 0))); // vertices.push_back(Vertex(Vector3f(-1, 1, -1), Vector2f(0, 1))); // // vertices.push_back(Vertex(Vector3f(1, -1, -1), Vector2f(1, 1))); // vertices.push_back(Vertex(Vector3f(1, -1, 1), Vector2f(1, 0))); // vertices.push_back(Vertex(Vector3f(1, 1, 1), Vector2f(0, 0))); // vertices.push_back(Vertex(Vector3f(1, 1, -1), Vector2f(0, 1))); // // indices.push_back(0); // indices.push_back(1); // indices.push_back(2); // indices.push_back(0); // indices.push_back(2); // indices.push_back(3); // // indices.push_back(6); // indices.push_back(5); // indices.push_back(4); // indices.push_back(7); // indices.push_back(6); // indices.push_back(4); // // indices.push_back(10); // indices.push_back(9); // indices.push_back(8); // indices.push_back(11); // indices.push_back(10); // indices.push_back(8); // // indices.push_back(12); // indices.push_back(13); // indices.push_back(14); // indices.push_back(12); // indices.push_back(14); // indices.push_back(15); // // indices.push_back(16); // indices.push_back(17); // indices.push_back(18); // indices.push_back(16); // indices.push_back(18); // indices.push_back(19); // // indices.push_back(22); // indices.push_back(21); // indices.push_back(20); // indices.push_back(23); // indices.push_back(22); // indices.push_back(20); vertices.push_back(Vertex(Vector3f(-1.0f, -1.0f, 0.5773f), Vector2f(0.0f, 0.0f))); vertices.push_back(Vertex(Vector3f(0.0f, -1.0f, -1.15475f), Vector2f(0.5f, 0.0f))); vertices.push_back(Vertex(Vector3f(1.0f, -1.0f, 0.5773f), Vector2f(1.0f, 0.0f))); vertices.push_back(Vertex(Vector3f(0.0f, 1.0f, 0.0f), Vector2f(0.5f, 1.0f))); indices.push_back(0); indices.push_back(3); indices.push_back(1); indices.push_back(1); indices.push_back(3); indices.push_back(2); indices.push_back(2); indices.push_back(3); indices.push_back(0); indices.push_back(1); indices.push_back(2); indices.push_back(0); model.addVertices(vertices, indices, true); Material material = Material(m_texture, Vector3f(1.0f, 1.0f, 1.0f), 2.0f, 32.0f); Mesh mesh0 = Mesh(model, material); // IndexedModel model1 = IndexedModel(); // model1.addVertex(Vertex(Vector3f(-5, -3, -5), Vector2f(0, 1))); // model1.addVertex(Vertex(Vector3f(-5, -3, 5), Vector2f(1, 1))); // model1.addVertex(Vertex(Vector3f( 5, -3, 5), Vector2f(1, 0))); // model1.addVertex(Vertex(Vector3f( 5, -3, -5), Vector2f(0, 0))); // model1.addFace(Vector3i(2, 1, 0)); // model1.addFace(Vector3i(3, 2, 0)); // Mesh mesh1 = Mesh(model1); // m_camera = new Camera(Vector3f(0.0f, 0.0f, -3.0f), Vector3f(0.0f, 0.0f, 1.0f), Vector3f(0.0f, 1.0f, 0.0f), 70.0f, m_engine->getWindow()->getAspectRatio(), 0.1f, 1000.0f); m_object0 = (new Entity())->addComponent(new MeshRenderer(mesh0)); add(m_object0); m_object0->getTransform().setRotation(Quaternion(Vector3f(1.0f, 0.0f, 1.0f).normalized(), MATH_PI)); // m_object1 = (new Entity())->addComponent(new MeshRenderer(mesh1)); // add(m_object1); add((new Entity())->addComponent(new CameraComponent(70.0f, m_engine->getWindow()->getAspectRatio(), 0.1f, 1000.0f)) ->addComponent(new FreeMove(0.2f)) ->addComponent(new FreeLook(m_engine->getWindow()->getCenter(), 0.2f))); m_engine->getRenderingEngine()->setAmbientLight(Vector3f(0.1f, 0.1f, 0.1f)); m_engine->getRenderingEngine()->setDirectionalLight(DirectionalLight(Light(Vector3f(1.0f, 1.0f, 1.0f), 0.8f), Vector3f(0.0f, 1.0f, 0.0f).normalized())); }
void TestGame::Init(const Window& window) { //Materials Material bricks("bricks", Texture("bricks.jpg"), 0.0f, 0, Texture("bricks_normal.jpg"), Texture("bricks_disp.png"), 0.03f, -0.5f); Material bricks2("bricks2", Texture("bricks2.jpg"), 0.0f, 0, Texture("bricks2_normal.png"), Texture("bricks2_disp.jpg"), 0.04f, -1.0f); //Standard square mesh (1x1) IndexedModel square; { square.AddVertex(1.0f, -1.0f, 0.0f); square.AddTexCoord(Vector2f(1.0f, 1.0f)); square.AddVertex(1.0f, 1.0f, 0.0f); square.AddTexCoord(Vector2f(1.0f, 0.0f)); square.AddVertex(-1.0f, -1.0f, 0.0f); square.AddTexCoord(Vector2f(0.0f, 1.0f)); square.AddVertex(-1.0f, 1.0f, 0.0f); square.AddTexCoord(Vector2f(0.0f, 0.0f)); square.AddFace(0, 1, 2); square.AddFace(2, 1, 3); } Mesh customMesh("square", square.Finalize()); //Light Entity* mainLight = new Entity(Vector3f(0, 4, 0), Quaternion(Vector3f(1, 0, 0), ToRadians(270)), 1); Entity* pointLight = new Entity(Vector3f(-1, 1.5, 0), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); mainLight->AddModifier(new DirectionalLight(Vector3f(1, 1, 1), 0.4f, 10, 80, 1)); pointLight->AddModifier(new PointLight(Vector3f(0, 0, 1), 0.4f, Attenuation(0, 0, 1))); pointLight->AddModifier(new RepetitiveLinearMotionModifier(Vector3f(1, 0, 0), 0.015f, 1)); //pointLight->AddModifier(new FreeMove(5.0f)); AddToScene(mainLight); //AddToScene(pointLight); //Camera Entity* mainCamera = new Entity(Vector3f(-10, 5, 5), Quaternion(Vector3f(0, 0, 0), 0), 1); mainCamera->AddModifier(new CameraComponent(Matrix4f().InitPerspective(ToRadians(70), window.GetAspect(), 0.1f, 1000))); mainCamera->AddModifier(new FreeLook(window.GetCenter(), 0.15f)); mainCamera->AddModifier(new FreeMove(15)); AddToScene(mainCamera); //Environment /*Entity* floorPlane = new Entity(Vector3f(0, 0, 0), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); Entity* floatingCube = new Entity(Vector3f(0, 1, 0), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 0.3f); floorPlane->AddModifier(new MeshRenderer(Mesh("plane.obj"), Material("bricks"))); floatingCube->AddModifier(new MeshRenderer(Mesh("cube.obj"), Material("bricks2"))); floatingCube->AddModifier(new RepetitiveLinearMotionModifier(Vector3f(0, 1, 0), 0.01f, 2)); floatingCube->AddModifier(new RepetitiveRotationalMotionModifier(Vector3f(0, 1, 0), 0.02f, 1, false)); AddToScene(floorPlane); AddToScene(floatingCube);*/ Entity* sphere1 = new Entity(Vector3f(0, 0, -4), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); Entity* sphere2 = new Entity(Vector3f(0, 0, 1), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); Entity* sphere3 = new Entity(Vector3f(0, 0, 3), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); Entity* sphere4 = new Entity(Vector3f(0, 0, 5), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); Entity* sphere5 = new Entity(Vector3f(0, 0, 7), Quaternion(Vector3f(0, 0, 0), ToRadians(0)), 1); sphere1->AddModifier(new MeshRenderer(Mesh("sphere.obj"), Material("bricks"))); sphere2->AddModifier(new MeshRenderer(Mesh("sphere.obj"), Material("bricks2"))); sphere3->AddModifier(new MeshRenderer(Mesh("sphere.obj"), Material("bricks2"))); sphere4->AddModifier(new MeshRenderer(Mesh("sphere.obj"), Material("bricks2"))); sphere5->AddModifier(new MeshRenderer(Mesh("sphere.obj"), Material("bricks"))); AddToScene(sphere1); AddToScene(sphere2); AddToScene(sphere3); AddToScene(sphere4); AddToScene(sphere5); //Physics PhysicsEngine physicsEngine = PhysicsEngine(); PhysicsObject sphere1Rep = PhysicsObject(sphere1, new BoundingSphere(Vector3f(0, 0, -4), 1), Vector3f(0, 0, 1), Vector3f(0, 0, 0), false); PhysicsObject sphere2Rep = PhysicsObject(sphere2, new BoundingSphere(Vector3f(0, 0, 1), 1), Vector3f(0, 0, 0), Vector3f(0, 0, 0), false); PhysicsObject sphere3Rep = PhysicsObject(sphere3, new BoundingSphere(Vector3f(0, 0, 3), 1), Vector3f(0, 0, 0), Vector3f(0, 0, 0), false); PhysicsObject sphere4Rep = PhysicsObject(sphere4, new BoundingSphere(Vector3f(0, 0, 5), 1), Vector3f(0, 0, 0), Vector3f(0, 0, 0), false); PhysicsObject sphere5Rep = PhysicsObject(sphere5, new BoundingSphere(Vector3f(0, 0, 7), 1), Vector3f(0, 0, 0), Vector3f(0, 0, 0), false); physicsEngine.AddObject(sphere1Rep); physicsEngine.AddObject(sphere2Rep); physicsEngine.AddObject(sphere3Rep); physicsEngine.AddObject(sphere4Rep); physicsEngine.AddObject(sphere5Rep); SetPhysicsEngine(physicsEngine); }
IndexedModel OBJModel::ToIndexedModel() { IndexedModel result; IndexedModel normalModel; unsigned int numIndices = OBJIndices.size(); std::vector<OBJIndex*> indexLookup; for(unsigned int i = 0; i < numIndices; i++) indexLookup.push_back(&OBJIndices[i]); std::sort(indexLookup.begin(), indexLookup.end(), CompareOBJIndexPtr); std::map<OBJIndex, unsigned int> normalModelIndexMap; std::map<unsigned int, unsigned int> indexMap; for(unsigned int i = 0; i < numIndices; i++) { OBJIndex* currentIndex = &OBJIndices[i]; glm::vec3 currentPosition = vertices[currentIndex->vertexIndex]; glm::vec2 currentTexCoord; glm::vec3 currentNormal; if(hasUVs) currentTexCoord = uvs[currentIndex->uvIndex]; else currentTexCoord = glm::vec2(0,0); if(hasNormals) currentNormal = normals[currentIndex->normalIndex]; else currentNormal = glm::vec3(0,0,0); unsigned int normalModelIndex; unsigned int resultModelIndex; //Create model to properly generate normals on std::map<OBJIndex, unsigned int>::iterator it = normalModelIndexMap.find(*currentIndex); if(it == normalModelIndexMap.end()) { normalModelIndex = normalModel.positions.size(); normalModelIndexMap.insert(std::pair<OBJIndex, unsigned int>(*currentIndex, normalModelIndex)); normalModel.positions.push_back(currentPosition); normalModel.texCoords.push_back(currentTexCoord); normalModel.normals.push_back(currentNormal); } else normalModelIndex = it->second; //Create model which properly separates texture coordinates unsigned int previousVertexLocation = FindLastVertexIndex(indexLookup, currentIndex, result); if(previousVertexLocation == (unsigned int)-1) { resultModelIndex = result.positions.size(); result.positions.push_back(currentPosition); result.texCoords.push_back(currentTexCoord); result.normals.push_back(currentNormal); } else resultModelIndex = previousVertexLocation; normalModel.indices.push_back(normalModelIndex); result.indices.push_back(resultModelIndex); indexMap.insert(std::pair<unsigned int, unsigned int>(resultModelIndex, normalModelIndex)); } if(!hasNormals) { normalModel.CalcNormals(); for(unsigned int i = 0; i < result.positions.size(); i++) result.normals[i] = normalModel.normals[indexMap[i]]; } return result; };
std::vector<IndexedModel> OBJModel::ToIndexedModel() { GLint vertexPos = 0, uvPos = 0; for each (Group group in GroupList) { IndexedModel result; IndexedModel normalModel; unsigned int numIndices = group.OBJIndices.size(); std::vector<OBJIndex*> indexLookup; for (unsigned int i = 0; i < numIndices; i++) indexLookup.push_back(&group.OBJIndices[i]); std::sort(indexLookup.begin(), indexLookup.end(), CompareOBJIndexPtr); std::map<OBJIndex, unsigned int> normalModelIndexMap; std::map<unsigned int, unsigned int> indexMap; vertexPos += (group.id > 0) ? GroupList[group.id - 1].vertices.size() : 0; uvPos += (group.id > 0) ? GroupList[group.id - 1].uvs.size() : 0; for (unsigned int i = 0; i < numIndices; i++) { OBJIndex* currentIndex = &group.OBJIndices[i]; glm::vec3 currentPosition = group.vertices[currentIndex->vertexIndex - vertexPos]; glm::vec2 currentTexCoord; glm::vec3 currentNormal; if (group.hasUVs) currentTexCoord = group.uvs[currentIndex->uvIndex - uvPos]; else currentNormal = glm::vec3(0, 0, 0); unsigned int normalModelIndex; unsigned int resultModelIndex; std::map<OBJIndex, unsigned int>::iterator it = normalModelIndexMap.find(*currentIndex); if (it == normalModelIndexMap.end()) { normalModelIndex = normalModel.positions.size(); normalModelIndexMap.insert(std::pair<OBJIndex, unsigned int>(*currentIndex, normalModelIndex)); normalModel.positions.push_back(currentPosition); normalModel.texCoords.push_back(currentTexCoord); normalModel.normals.push_back(currentNormal); } else normalModelIndex = it->second; unsigned int previousVertexLocation = FindLastVertexIndex(group, indexLookup, currentIndex, result); if (previousVertexLocation == (unsigned int)-1) { resultModelIndex = result.positions.size(); result.positions.push_back(currentPosition); result.texCoords.push_back(currentTexCoord); result.normals.push_back(currentNormal); } else resultModelIndex = previousVertexLocation; normalModel.indices.push_back(normalModelIndex); result.indices.push_back(resultModelIndex); indexMap.insert(std::pair<unsigned int, unsigned int>(resultModelIndex, normalModelIndex)); } if (!group.hasNormals) { normalModel.CalcNormals(); for (unsigned int i = 0; i < result.positions.size(); i++) { result.normals[i] = normalModel.normals[indexMap[i]]; } } result.hasUVs = group.hasUVs; result.hasNormals = group.hasNormals; IndexedModelList.push_back(result); }
MeshData::MeshData(const IndexedModel& model) : ReferenceCounter(), m_drawCount(model.GetIndices().size()) { if(!model.IsValid()) { std::cout << "Error: Invalid mesh! Must have same number of positions, texCoords, normals, and tangents! " << "(Maybe you forgot to Finalize() your IndexedModel?)" << std::endl; assert(0 != 0); } glGenVertexArrays(1, &m_vertexArrayObject); glBindVertexArray(m_vertexArrayObject); glGenBuffers(NUM_BUFFERS, m_vertexArrayBuffers); glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[POSITION_VB]); glBufferData(GL_ARRAY_BUFFER, model.GetPositions().size() * sizeof(model.GetPositions()[0]), &model.GetPositions()[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TEXCOORD_VB]); glBufferData(GL_ARRAY_BUFFER, model.GetTexCoords().size() * sizeof(model.GetTexCoords()[0]), &model.GetTexCoords()[0], GL_STATIC_DRAW); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[NORMAL_VB]); glBufferData(GL_ARRAY_BUFFER, model.GetNormals().size() * sizeof(model.GetNormals()[0]), &model.GetNormals()[0], GL_STATIC_DRAW); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ARRAY_BUFFER, m_vertexArrayBuffers[TANGENT_VB]); glBufferData(GL_ARRAY_BUFFER, model.GetTangents().size() * sizeof(model.GetTangents()[0]), &model.GetTangents()[0], GL_STATIC_DRAW); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vertexArrayBuffers[INDEX_VB]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, model.GetIndices().size() * sizeof(model.GetIndices()[0]), &model.GetIndices()[0], GL_STATIC_DRAW); }