// This is used in icosphere generation. int getMiddlePoint(int p1, int p2) { // first check if we have it already /*bool firstIsSmaller = p1 < p2; int smallerIndex = firstIsSmaller ? p1 : p2; int greaterIndex = firstIsSmaller ? p2 : p1; int key = (smallerIndex << 32) + greaterIndex; int ret; if (this.middlePointIndexCache.TryGetValue(key, out ret)) { return ret; }*/ // not in cache, calculate it VertexFormat point1 = vertices[p1]; VertexFormat point2 = vertices[p2]; VertexFormat middle = VertexFormat(glm::vec3((point1.position.x + point2.position.x) / 2.0, (point1.position.y + point2.position.y) / 2.0, (point1.position.z + point2.position.z) / 2.0), glm::vec4(((float)(rand() % 100)) / 99.0f, ((float)(rand() % 100)) / 99.0f, 0.0f, ((float)(rand() % 100)) / 99.0f)); double length = sqrt(middle.position.x * middle.position.x + middle.position.y * middle.position.y + middle.position.z * middle.position.z); vertices.push_back(VertexFormat(glm::vec3(middle.position.x / length, middle.position.y / length, middle.position.z / length), glm::vec4(((float)(rand() % 100)) / 99.0f, ((float)(rand() % 100)) / 99.0f, ((float)(rand() % 100)) / 99.0f, 1.0f))); // add vertex makes sure point is on unit sphere int i = vertices.size() - 1; // store it, return index return i; }
VertexFormat* Mesh::GenerateParticle(float size) { VertexFormat* verts = new VertexFormat[4]; verts[0] = VertexFormat(-size / 2, -size / 2, 0, 255, 255, 255, 255, 0, 0, 0, 0, -1); verts[1] = VertexFormat(-size / 2, size / 2, 0, 255, 255, 255, 255, 0, 1, 0, 0, -1); verts[2] = VertexFormat(size / 2, size / 2, 0, 255, 255, 255, 255, 1, 1, 0, 0, -1); verts[3] = VertexFormat(size / 2, -size / 2, 0, 255, 255, 255, 255, 1, 0, 0, 0, -1); return verts; }
//This function sets up the two shapes we need for this example. void setup() { int NumberOfDivisions = 20; line.point1 = glm::vec3(-0.5f, 0.5f, 0.0f); line.point2 = glm::vec3(-0.5f, -0.5f, 0.0f); float radius = 0.25f; cylinder.radius = radius; cylinder.point1 = glm::vec3(0.0f, 0.5f, 0.0f); cylinder.point2 = glm::vec3(0.0f, -0.5f, 0.0f); VertexFormat center1(cylinder.point1, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); VertexFormat center2(cylinder.point2, glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); std::vector<VertexFormat> vertices; float height = glm::distance(cylinder.point1, cylinder.point2); float theta = 360.0f / NumberOfDivisions; VertexFormat A, B, C, D; //Circle vertex generation //In this example we are not implementing the proper the code for indices. We are just going to produce redundant information in the buffer. //since we are only having a small number of objects on the screen currently, this redundancy should not matter. for (int i = 0; i < NumberOfDivisions; i++) { A = VertexFormat(glm::vec3(radius * cos(glm::radians(i*theta)),0.5f, radius * sin(glm::radians(i*theta))), glm::vec4(0.7f, 0.20f, 0.0f, 1.0f)); B = VertexFormat(glm::vec3(radius * cos(glm::radians((i + 1)*theta)), 0.5f, radius * sin(glm::radians((i + 1)*theta))), glm::vec4(0.7f, 0.20f, 0.0f, 1.0f)); C = VertexFormat(glm::vec3(radius * cos(glm::radians(i*theta)), -0.5f, radius * sin(glm::radians(i*theta))), glm::vec4(0.0f, 0.20f, 0.7f, 1.0f)); D = VertexFormat(glm::vec3(radius * cos(glm::radians((i + 1)*theta)), -0.5f, radius * sin(glm::radians((i + 1)*theta))), glm::vec4(0.0f, 0.20f, 0.7f, 1.0f)); //In every iteration, the center, the point at angle theta and at angle (theta+delta) are fed into the buffer. vertices.push_back(center1); vertices.push_back(A); vertices.push_back(B); vertices.push_back(center2); vertices.push_back(C); vertices.push_back(D); vertices.push_back(A); vertices.push_back(C); vertices.push_back(B); vertices.push_back(C); vertices.push_back(D); vertices.push_back(B); } cylinder.base.initBuffer(12 * NumberOfDivisions, &vertices[0]); }
Mesh* Mesh::createQuad(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4) { // Calculate the normal vector of the plane. Vector3 v1, v2, n; Vector3::subtract(p2, p1, &v1); Vector3::subtract(p3, p2, &v2); Vector3::cross(v1, v2, &n); n.normalize(); float vertices[] = { p1.x, p1.y, p1.z, n.x, n.y, n.z, 0, 1, p2.x, p2.y, p2.z, n.x, n.y, n.z, 0, 0, p3.x, p3.y, p3.z, n.x, n.y, n.z, 1, 1, p4.x, p4.y, p4.z, n.x, n.y, n.z, 1, 0 }; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::NORMAL, 3), VertexFormat::Element(VertexFormat::TEXCOORD0, 2) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 3), 4, false); if (mesh == NULL) { return NULL; } mesh->_primitiveType = TRIANGLE_STRIP; mesh->setVertexData(vertices, 0, 4); return mesh; }
Mesh* Mesh::createQuadFullscreen() { float x = -1.0f; float y = -1.0f; float x2 = 1.0f; float y2 = 1.0f; float vertices[] = { x, y2, 0, 0, x, y, 0, 1, x2, y2, 1, 0, x2, y, 1, 1 }; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 2), VertexFormat::Element(VertexFormat::TEXCOORD0, 2) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), 4, false); if (mesh == NULL) { return NULL; } mesh->_primitiveType = TRIANGLE_STRIP; mesh->setVertexData(vertices, 0, 4); return mesh; }
static Mesh* createPointsMesh() { float scale = 0.2f; unsigned int vertexCount = 100; std::vector<float> vertices; vertices.reserve(vertexCount * 6); for (unsigned int i = 0; i < vertexCount; ++i) { // x, y, z, r, g, b vertices.push_back(MATH_RANDOM_MINUS1_1() * scale); vertices.push_back(MATH_RANDOM_MINUS1_1() * scale); vertices.push_back(MATH_RANDOM_MINUS1_1() * scale); vertices.push_back(MATH_RANDOM_0_1()); vertices.push_back(MATH_RANDOM_0_1()); vertices.push_back(MATH_RANDOM_0_1()); } VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), vertexCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->setPrimitiveType(Mesh::POINTS); mesh->setVertexData(&vertices[0], 0, vertexCount); return mesh; }
void Scene::drawDebug(unsigned int debugFlags) { if (_debugBatch == NULL) { Material* material = createDebugMaterial(); VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 4) }; _debugBatch = MeshBatch::create(VertexFormat(elements, 2), Mesh::LINES, material, false); SAFE_RELEASE(material); } _debugBatch->start(); for (Node* node = _firstNode; node != NULL; node = node->_nextSibling) { drawDebugNode(_debugBatch, node, debugFlags); } _debugBatch->finish(); if (_activeCamera) { GP_ASSERT(_debugBatch->getMaterial()); GP_ASSERT(_debugBatch->getMaterial()->getParameter("u_viewProjectionMatrix")); _debugBatch->getMaterial()->getParameter("u_viewProjectionMatrix")->setValue(_activeCamera->getViewProjectionMatrix()); } _debugBatch->draw(); }
Mesh* Mesh::createLines(Vector3* points, unsigned int pointCount) { GP_ASSERT(points); GP_ASSERT(pointCount); float* vertices = new float[pointCount*3]; memcpy(vertices, points, pointCount*3*sizeof(float)); VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 1), pointCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); SAFE_DELETE_ARRAY(vertices); return NULL; } mesh->_primitiveType = LINE_STRIP; mesh->setVertexData(vertices, 0, pointCount); SAFE_DELETE_ARRAY(vertices); return mesh; }
static Mesh* createLineStripMesh() { float a = 0.1f; float vertices[] = { 0, 0, 0, 1, 0, 0, a, 0, -a, 0, 1, 0, 0, -a, a, 0, 0, 1, -a, 0, -a, 1, 0, 1, 0, a, a, 0, 1, 1, }; unsigned int vertexCount = 5; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), vertexCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->setPrimitiveType(Mesh::LINE_STRIP); mesh->setVertexData(vertices, 0, vertexCount); return mesh; }
int gamehsp::makeNewMat2D( char *fname, int matopt ) { gpmat *mat = addMat(); if ( mat == NULL ) return -1; Material *mesh_material = makeMaterialTex2D( fname, matopt ); if ( mesh_material == NULL ) return -1; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::TEXCOORD0, 2), VertexFormat::Element(VertexFormat::COLOR, 4) }; unsigned int elementCount = sizeof(elements) / sizeof(VertexFormat::Element); MeshBatch *meshBatch = MeshBatch::create(VertexFormat(elements, elementCount), Mesh::TRIANGLE_STRIP, mesh_material, true, 16, 256 ); mat->_mesh = meshBatch; mat->_material = mesh_material; mat->_mode = GPMAT_MODE_2D; mat->_sx = _tex_width; mat->_sy = _tex_height; mat->_texratex = 1.0f / (float)_tex_width; mat->_texratey = 1.0f / (float)_tex_height; return mat->_id; }
/** * Creates a triangle mesh with vertex colors. */ static Mesh* createTriangleMesh() { // Calculate the vertices of the equilateral triangle. float a = 0.5f; // length of the side Vector2 p1(0.0f, a / sqrtf(3.0f)); Vector2 p2(-a / 2.0f, -a / (2.0f * sqrtf(3.0f))); Vector2 p3( a / 2.0f, -a / (2.0f * sqrtf(3.0f))); // Create 3 vertices. Each vertex has position (x, y, z) and color (red, green, blue) float vertices[] = { p1.x, p1.y, 0.0f, 1.0f, 0.0f, 0.0f, p2.x, p2.y, 0.0f, 0.0f, 1.0f, 0.0f, p3.x, p3.y, 0.0f, 0.0f, 0.0f, 1.0f, }; unsigned int vertexCount = 3; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), vertexCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->setPrimitiveType(Mesh::TRIANGLES); mesh->setVertexData(vertices, 0, vertexCount); return mesh; }
Mesh* Mesh::createQuad(float x, float y, float width, float height) { float x2 = x + width; float y2 = y + height; float vertices[] = { x, y2, 0, 0, 0, 1, 0, 0, x, y, 0, 0, 0, 1, 0, 1, x2, y2, 0, 0, 0, 1, 1, 0, x2, y, 0, 0, 0, 1, 1, 1 }; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::NORMAL, 3), VertexFormat::Element(VertexFormat::TEXCOORD0, 2) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 3), 4, false); if (mesh == NULL) { return NULL; } mesh->_primitiveType = TRIANGLE_STRIP; mesh->setVertexData(vertices, 0, 4); return mesh; }
void Quad::Create() { GLuint vao; GLuint vbo; GLuint ibo; // Create and bind vertex array object glGenVertexArrays(1, &vao); glBindVertexArray(vao); // Define vertices std::vector<VertexFormat> vertices; vertices.push_back(VertexFormat(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(0.5f, -0.5f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(0.5f, 0.5f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(-0.5f, 0.5f, 0.0f), glm::vec4(1.0f, 0.0f, 1.0f, 1.0f))); // IBO data GLuint indexData[] = { 0, 1, 2, 2, 3, 0 }; // Create VBO glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(VertexFormat), &vertices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)12); // Create IBO glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), indexData, GL_STATIC_DRAW); glBindVertexArray(0); // Setup mesh this->m_uiVao = vao; this->m_uiVbo = vbo; this->m_uiIbo = ibo; // Get references to the uniform variables m_uiModelMatrixUniform = glGetUniformLocation(m_uiProgram, "model"); m_uiViewMatrixUniform = glGetUniformLocation(m_uiProgram, "view"); m_uiProjectionMatrixUniform = glGetUniformLocation(m_uiProgram, "projection"); }
void Form::setNode(Node* node) { // If the user wants a custom node then we need to create a 3D quad if (node && node != _node) { // Set this Form up to be 3D by initializing a quad. float x2 = _bounds.width; float y2 = _bounds.height; float vertices[] = { 0, y2, 0, 0, _v1, 0, 0, 0, 0, 0, x2, y2, 0, _u2, _v1, x2, 0, 0, _u2, 0 }; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::TEXCOORD0, 2) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), 4, false); GP_ASSERT(mesh); mesh->setPrimitiveType(Mesh::TRIANGLE_STRIP); mesh->setVertexData(vertices, 0, 4); _nodeQuad = Model::create(mesh); SAFE_RELEASE(mesh); GP_ASSERT(_nodeQuad); // Create the effect and material Effect* effect = createEffect(); GP_ASSERT(effect); _nodeMaterial = Material::create(effect); GP_ASSERT(_nodeMaterial); _nodeQuad->setMaterial(_nodeMaterial); _nodeMaterial->release(); node->setModel(_nodeQuad); _nodeQuad->release(); // Bind the WorldViewProjection matrix. _nodeMaterial->setParameterAutoBinding("u_worldViewProjectionMatrix", RenderState::WORLD_VIEW_PROJECTION_MATRIX); // Bind the texture from the framebuffer and set the texture to clamp Texture::Sampler* sampler = Texture::Sampler::create(_frameBuffer->getRenderTarget()->getTexture()); GP_ASSERT(sampler); sampler->setWrapMode(Texture::CLAMP, Texture::CLAMP); _nodeMaterial->getParameter("u_texture")->setValue(sampler); sampler->release(); RenderState::StateBlock* rsBlock = _nodeMaterial->getStateBlock(); rsBlock->setDepthWrite(true); rsBlock->setBlend(true); rsBlock->setBlendSrc(RenderState::BLEND_SRC_ALPHA); rsBlock->setBlendDst(RenderState::BLEND_ONE_MINUS_SRC_ALPHA); } _node = node; }
void drawPole() { unsigned int indices[] = { // spate 0, 1, 2, 2, 3, 0, // sus 3, 2, 6, 6, 7, 3, // fata 7, 6, 5, 5, 4, 7, // jos 4, 5, 1, 1, 0, 4, // stanga 4, 0, 3, 3, 7, 4, // dreapta 1, 5, 6, 6, 2, 1, }; std::vector<VertexFormat> vertices; vertices.push_back(VertexFormat(0, 0, 0)); vertices.push_back(VertexFormat(pole_width, 0, 0)); vertices.push_back(VertexFormat(pole_width, pole_width, 0)); vertices.push_back(VertexFormat(0, pole_width, 0)); vertices.push_back(VertexFormat(0, 0, pole_length)); vertices.push_back(VertexFormat(pole_width, 0, pole_length)); vertices.push_back(VertexFormat(pole_width, pole_width, pole_length)); vertices.push_back(VertexFormat(0, pole_width, pole_length)); pole_mesh_num_indices = sizeof(indices); glGenVertexArrays(1, &pole_vao); glBindVertexArray(pole_vao); //vertex buffer object -> un obiect in care tinem vertecsii glGenBuffers(1,&pole_vbo); glBindBuffer(GL_ARRAY_BUFFER, pole_vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(VertexFormat), &vertices[0], GL_STATIC_DRAW); //index buffer object -> un obiect in care tinem indecsii glGenBuffers(1,&pole_ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pole_ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(VertexFormat),(void*)0); //trimite pozitii pe pipe 0 glEnableVertexAttribArray(1); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(VertexFormat),(void*)(sizeof(float)*3)); //trimite normale pe pipe 1 }
//This function sets up the two shapes we need for this example. void setup() { //Set up the global variables. acc = glm::vec3(0.0f, 0.0f, 0.0f); force = glm::vec3(0.0f, 0.0f, 0.0f); //Setting up the Circle /* A large sphere with a smaller mass is more likely to float than a small sphere with the same mass as it displaces a larger amount of fluid and has a lesser weight. */ circle.origin = glm::vec3(0.0f, 0.1f, 0.2f); circle.velocity = glm::vec3(0.0f, 0.0f,0.0f); circle.radius = 0.25f; circle.mass = mass * 0.1f; circle.acceleration = glm::vec3(0.0f, 0.0f, 0.0f); float radius = circle.radius; VertexFormat center(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f)); std::vector<VertexFormat> vertices; float theta = 360.0f / NumberOfDivisions; //Circle vertex generation //In this example we are not implementing the proper the code for indices. We are just going to produce redundant information in the buffer. //since we are only having a small number of objects on the screen currently, this redundancy should not matter. for (int i = 0; i < NumberOfDivisions; i++) { //In every iteration, the center, the point at angle theta and at angle (theta+delta) are fed into the buffer. vertices.push_back(center); vertices.push_back(VertexFormat(glm::vec3(radius * cos(glm::radians(i*theta)), radius * sin(glm::radians(i*theta)), 0.0f), glm::vec4(0.7f, 0.20f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(radius * cos(glm::radians((i + 1)*theta)), radius * sin(glm::radians((i + 1)*theta)), 0.0f), glm::vec4(0.7f, 0.20f, 0.0f, 1.0f))); } circle.base.initBuffer(NumberOfDivisions * 3, &vertices[0]); //Set up the waterbody // This is water body is supposed to extend to infinity, but fo the purpose of this demonstration it will extend from -10 to 10 vertices.clear(); water.origin = glm::vec3(0.0f, 0.5f, 0.0f); water.length = 10.0f; water.breadth = 20.0f; vertices.push_back(VertexFormat(glm::vec3(-water.breadth, 0.0f, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(-water.breadth, -water.length, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(water.breadth, 0.0f, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(water.breadth, 0.0f, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(-water.breadth, -water.length, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(water.breadth, -water.length, 0.0f), glm::vec4(0.5f, 0.5f, 0.9f, 1.0f))); water.base.initBuffer(6, &vertices[0]); }
Mesh* Mesh::CreateBox(Vector2 size, bool isAnimated) { VertexFormat* verts = new VertexFormat[4]; verts[0] = VertexFormat( -size.x/2, -size.y/2, 0, 255,255,255,255, 0,0, 0,0,-1 ); verts[1] = VertexFormat( -size.x/2, size.y/2, 0, 255,255,255,255, 0,1, 0,0,-1 ); verts[2] = VertexFormat( size.x/2, size.y/2, 0, 255,255,255,255, 1,1, 0,0,-1 ); verts[3] = VertexFormat( size.x/2, -size.y/2, 0, 255,255,255,255, 1,0, 0,0,-1 ); unsigned int* indices = new unsigned int[6]; indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 0; indices[4] = 2; indices[5] = 3; float minX = verts[0].pos.x; float maxX = verts[0].pos.x; float minY = verts[0].pos.y; float maxY = verts[0].pos.y; for (uint i = 1; i < 4; i++) { minX = npw::Minimum(minX, verts[i].pos.x); maxX = npw::Maximum(maxX, verts[i].pos.x); minY = npw::Minimum(minY, verts[i].pos.y); maxY = npw::Maximum(maxY, verts[i].pos.y); } Mesh* pMesh; if (isAnimated) pMesh = new AnimatedMesh(); else pMesh = new Mesh(); pMesh->Init(verts, 4, indices, 6, GL_STATIC_DRAW); pMesh->SetWidth(size.x); pMesh->SetHeight(size.y); return pMesh; };
static Mesh* createCubeMesh(float size = 1.0f) { float a = size * 0.5f; float vertices[] = { -a, -a, a, 0.0, 0.0, 1.0, 0.0, 0.0, a, -a, a, 0.0, 0.0, 1.0, 1.0, 0.0, -a, a, a, 0.0, 0.0, 1.0, 0.0, 1.0, a, a, a, 0.0, 0.0, 1.0, 1.0, 1.0, -a, a, a, 0.0, 1.0, 0.0, 0.0, 0.0, a, a, a, 0.0, 1.0, 0.0, 1.0, 0.0, -a, a, -a, 0.0, 1.0, 0.0, 0.0, 1.0, a, a, -a, 0.0, 1.0, 0.0, 1.0, 1.0, -a, a, -a, 0.0, 0.0, -1.0, 0.0, 0.0, a, a, -a, 0.0, 0.0, -1.0, 1.0, 0.0, -a, -a, -a, 0.0, 0.0, -1.0, 0.0, 1.0, a, -a, -a, 0.0, 0.0, -1.0, 1.0, 1.0, -a, -a, -a, 0.0, -1.0, 0.0, 0.0, 0.0, a, -a, -a, 0.0, -1.0, 0.0, 1.0, 0.0, -a, -a, a, 0.0, -1.0, 0.0, 0.0, 1.0, a, -a, a, 0.0, -1.0, 0.0, 1.0, 1.0, a, -a, a, 1.0, 0.0, 0.0, 0.0, 0.0, a, -a, -a, 1.0, 0.0, 0.0, 1.0, 0.0, a, a, a, 1.0, 0.0, 0.0, 0.0, 1.0, a, a, -a, 1.0, 0.0, 0.0, 1.0, 1.0, -a, -a, -a, -1.0, 0.0, 0.0, 0.0, 0.0, -a, -a, a, -1.0, 0.0, 0.0, 1.0, 0.0, -a, a, -a, -1.0, 0.0, 0.0, 0.0, 1.0, -a, a, a, -1.0, 0.0, 0.0, 1.0, 1.0 }; short indices[] = { 0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7, 8, 9, 10, 10, 9, 11, 12, 13, 14, 14, 13, 15, 16, 17, 18, 18, 17, 19, 20, 21, 22, 22, 21, 23 }; unsigned int vertexCount = 24; unsigned int indexCount = 36; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::NORMAL, 3), VertexFormat::Element(VertexFormat::TEXCOORD0, 2) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 3), vertexCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->setVertexData(vertices, 0, vertexCount); MeshPart* meshPart = mesh->addPart(Mesh::TRIANGLES, Mesh::INDEX16, indexCount, false); meshPart->setIndexData(indices, 0, indexCount); return mesh; }
void drawFabric() { std::vector<VertexFormat> vertices; std::vector<unsigned int> indices; fabric_mesh_num_indices = 0; float granularity1 = 50; float granularity2 = granularity1 * fabric_length / fabric_width; for(float i = 0; i < granularity1; i++) for(float j = 0; j < granularity2; j++) { vertices.push_back(VertexFormat(j * fabric_width / granularity2, 0, i * fabric_length / granularity1, 0, 1, 0)); } for(float i = 0; i < granularity1 - 1; i++) for(float j = 0; j < granularity2 - 1; j++) { indices.push_back(i * granularity2 + j); indices.push_back((i + 1) * granularity2 + j); indices.push_back((i + 1) * granularity2 + j + 1); indices.push_back(i * granularity2 + j); indices.push_back((i + 1) * granularity2 + j + 1); indices.push_back(i * granularity2 + j + 1); fabric_mesh_num_indices += 6; } glGenVertexArrays(1, &fabric_vao); glBindVertexArray(fabric_vao); //vertex buffer object -> un obiect in care tinem vertecsii glGenBuffers(1,&fabric_vbo); glBindBuffer(GL_ARRAY_BUFFER, fabric_vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(VertexFormat), &vertices[0], GL_STATIC_DRAW); //index buffer object -> un obiect in care tinem indecsii glGenBuffers(1,&fabric_ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fabric_ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() *sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(VertexFormat),(void*)0); //trimite pozitii pe pipe 0 glEnableVertexAttribArray(1); glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,sizeof(VertexFormat),(void*)(sizeof(float)*3)); //trimite normale pe pipe 1 }
void Cube::CreateModelVectors(std::vector<VertexFormat> &vertices, std::vector<uint> &indices) { float halfSide = m_side / 2.f; //Up verices vertices.push_back(VertexFormat(Vec3(-halfSide, halfSide, -halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(-halfSide, halfSide, halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(halfSide, halfSide, halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(halfSide, halfSide, -halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); //Down Verties vertices.push_back(VertexFormat(Vec3(-halfSide, -halfSide, -halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(-halfSide, -halfSide, halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(halfSide, -halfSide, halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); vertices.push_back(VertexFormat(Vec3(halfSide, -halfSide, -halfSide), m_colored ? m_color : Vec3(RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f), RNG::Float(0.f, 1.f)))); //Up Faces indices.push_back(0), indices.push_back(1), indices.push_back(2); indices.push_back(0), indices.push_back(2), indices.push_back(3); //Front Faces indices.push_back(0), indices.push_back(3), indices.push_back(4); indices.push_back(4), indices.push_back(3), indices.push_back(7); //Right Faces indices.push_back(7), indices.push_back(3), indices.push_back(2); indices.push_back(7), indices.push_back(2), indices.push_back(6); //Back Faces indices.push_back(6), indices.push_back(2), indices.push_back(1); indices.push_back(6), indices.push_back(1), indices.push_back(5); //Left Faces indices.push_back(4), indices.push_back(1), indices.push_back(0); indices.push_back(4), indices.push_back(5), indices.push_back(1); //Down Faces indices.push_back(7), indices.push_back(6), indices.push_back(4); indices.push_back(4), indices.push_back(6), indices.push_back(5); }
Mesh* Mesh::createBoundingBox(const BoundingBox& box) { Vector3 corners[8]; box.getCorners(corners); float vertices[] = { corners[7].x, corners[7].y, corners[7].z, corners[6].x, corners[6].y, corners[6].z, corners[1].x, corners[1].y, corners[1].z, corners[0].x, corners[0].y, corners[0].z, corners[7].x, corners[7].y, corners[7].z, corners[4].x, corners[4].y, corners[4].z, corners[3].x, corners[3].y, corners[3].z, corners[0].x, corners[0].y, corners[0].z, corners[0].x, corners[0].y, corners[0].z, corners[1].x, corners[1].y, corners[1].z, corners[2].x, corners[2].y, corners[2].z, corners[3].x, corners[3].y, corners[3].z, corners[4].x, corners[4].y, corners[4].z, corners[5].x, corners[5].y, corners[5].z, corners[2].x, corners[2].y, corners[2].z, corners[1].x, corners[1].y, corners[1].z, corners[6].x, corners[6].y, corners[6].z, corners[5].x, corners[5].y, corners[5].z }; VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 1), 18, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->_primitiveType = LINE_STRIP; mesh->setVertexData(vertices, 0, 18); return mesh; }
static Mesh* createTriangleStripMesh() { float scale = 0.02f; unsigned int vertexCount = 20; std::vector<float> vertices; vertices.reserve(vertexCount * 6); float x = -0.2f; float y = -0.05f; float step = fabs(x) * 2.0f / (float)vertexCount; for (unsigned int i = 0; i < vertexCount; ++i) { // x, y, z, r, g, b vertices.push_back(x); vertices.push_back(y + MATH_RANDOM_MINUS1_1() * scale); vertices.push_back(MATH_RANDOM_MINUS1_1() * scale * 2); vertices.push_back(MATH_RANDOM_0_1()); vertices.push_back(MATH_RANDOM_0_1()); vertices.push_back(MATH_RANDOM_0_1()); x += step; y *= -1.0f; } VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), vertexCount, false); if (mesh == NULL) { GP_ERROR("Failed to create mesh."); return NULL; } mesh->setPrimitiveType(Mesh::TRIANGLE_STRIP); // mesh->setVertexData(&vertices[0], 0, vertexCount); return mesh; }
Mesh* Mesh::LoadOBJFile(const char* objfilename, Vector3 scale) { long length = 0; char* buffer = LoadCompleteFile(objfilename, &length); if (buffer == 0 || length == 0) { delete buffer; return nullptr; } char* next_token = 0; char* line = strtok_s(buffer, "\n", &next_token); std::vector<Vector3> positions; std::vector<Vector2> uvCoords; std::vector<Vector3> normals; std::vector<VertexFormat> verts; std::vector<unsigned int> inds; unsigned int indcounter = 0; while (line) { Vector3 Pos; Vector2 Uv; Vector3 Normal; int p1; int uv1; int norm1; int p2; int uv2; int norm2; int p3; int uv3; int norm3; if (sscanf_s(line, "v %f %f %f", &Pos.x, &Pos.y, &Pos.z)) { positions.push_back(Pos); } else if (sscanf_s(line, "vt %f %f", &Uv.x, &Uv.y)) { uvCoords.push_back(Uv); } else if (sscanf_s(line, "vn %f %f %f", &Normal.x, &Normal.y, &Normal.z)) { normals.push_back(Normal); } else if (sscanf_s(line, "f %u/%u/%u %u/%u/%u %u/%u/%u", &p1, &uv1, &norm1, &p2, &uv2, &norm2, &p3, &uv3, &norm3)) { verts.push_back(VertexFormat( positions[p1 - 1].x * scale.x, positions[p1 - 1].y * scale.y, positions[p1 - 1].z * scale.z, 255,255,255,255, uvCoords[uv1 - 1].x, uvCoords[uv1 - 1].y, normals[norm1 - 1].x, normals[norm1 - 1].y, normals[norm1 - 1].z)); verts.push_back(VertexFormat( positions[p2 - 1].x * scale.x, positions[p2 - 1].y * scale.y, positions[p2 - 1].z * scale.z, 255,255,255,255, uvCoords[uv2 - 1].x, uvCoords[uv2 - 1].y, normals[norm2 - 1].x, normals[norm2 - 1].y, normals[norm2 - 1].z)); verts.push_back(VertexFormat( positions[p3 - 1].x * scale.x, positions[p3 - 1].y * scale.y, positions[p3 - 1].z * scale.z, 255,255,255,255, uvCoords[uv3 - 1].x, uvCoords[uv3 - 1].y, normals[norm3 - 1].x, normals[norm3 - 1].y, normals[norm3 - 1].z)); inds.push_back(indcounter); inds.push_back(indcounter + 1); inds.push_back(indcounter + 2); indcounter += 3; } line = strtok_s(0, "\n", &next_token); } float minX = positions[0].x; float maxX = positions[0].x; float minY = positions[0].y; float maxY = positions[0].y; for (uint i = 1; i < positions.size(); i++) { minX = npw::Minimum(minX, positions[i].x); maxX = npw::Maximum(maxX, positions[i].x); minY = npw::Minimum(minY, positions[i].y); maxY = npw::Maximum(maxY, positions[i].y); } VertexFormat* pointerverts = new VertexFormat[verts.size()]; for (unsigned int i = 0; i < verts.size(); i++) pointerverts[i] = verts[i]; unsigned int* pointerinds = new unsigned int[inds.size()]; for (unsigned int i = 0; i < inds.size(); i++) pointerinds[i] = inds[i]; Mesh* pMesh = new Mesh(); pMesh->Init(pointerverts, verts.size(), pointerinds, inds.size(), GL_STATIC_DRAW); pMesh->SetWidth((maxX - minX) * scale.x); pMesh->SetHeight((maxY - minY) * scale.y); return pMesh; }
// Initialization code void init() { // Initializes the glew library glewInit(); // Create an std::vector and put our vertices into it. These are just hardcoded values here defined once. std::vector<VertexFormat> vertices; vertices.push_back(VertexFormat(glm::vec2(1.0, 1.0), glm::vec3(0.25, -0.25, 0.0))); // bottom right vertices.push_back(VertexFormat(glm::vec2(0.0, 1.0), glm::vec3(-0.25, -0.25, 0.0)));// bottom left vertices.push_back(VertexFormat(glm::vec2(1.0, 0.0), glm::vec3(0.25, 0.25, 0.0))); // top right vertices.push_back(VertexFormat(glm::vec2(1.0, 0.0), glm::vec3(0.25, 0.25, 0.0))); // top right vertices.push_back(VertexFormat(glm::vec2(0.0, 1.0), glm::vec3(-0.25, -0.25, 0.0)));// bottom left vertices.push_back(VertexFormat(glm::vec2(0.0, 0.0), glm::vec3(-0.25, 0.25, 0.0))); // top left // This generates buffer object names // The first parameter is the number of buffer objects, and the second parameter is a pointer to an array of buffer objects (yes, before this call, vbo was an empty variable) // (In this example, there's only one buffer object.) glGenBuffers(1, &vbo); // Binds a named buffer object to the specified buffer binding point. Give it a target (GL_ARRAY_BUFFER) to determine where to bind the buffer. // There are several different target parameters, GL_ARRAY_BUFFER is for vertex attributes, feel free to Google the others to find out what else there is. // The second paramter is the buffer object reference. If no buffer object with the given name exists, it will create one. // Buffer object names are unsigned integers (like vbo). Zero is a reserved value, and there is no default buffer for each target (targets, like GL_ARRAY_BUFFER). // Passing in zero as the buffer name (second parameter) will result in unbinding any buffer bound to that target, and frees up the memory. glBindBuffer(GL_ARRAY_BUFFER, vbo); // Creates and initializes a buffer object's data. // First parameter is the target, second parameter is the size of the buffer, third parameter is a pointer to the data that will copied into the buffer, and fourth parameter is the // expected usage pattern of the data. Possible usage patterns: GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, GL_DYNAMIC_DRAW, // GL_DYNAMIC_READ, or GL_DYNAMIC_COPY // Stream means that the data will be modified once, and used only a few times at most. Static means that the data will be modified once, and used a lot. Dynamic means that the data // will be modified repeatedly, and used a lot. Draw means that the data is modified by the application, and used as a source for GL drawing. Read means the data is modified by // reading data from GL, and used to return that data when queried by the application. Copy means that the data is modified by reading from the GL, and used as a source for drawing. glBufferData(GL_ARRAY_BUFFER, sizeof(VertexFormat) * 6, &vertices[0], GL_STATIC_DRAW); // By default, all client-side capabilities are disabled, including all generic vertex attribute arrays. // When enabled, the values in a generic vertex attribute array will be accessed and used for rendering when calls are made to vertex array commands (like glDrawArrays/glDrawElements) // A GL_INVALID_VALUE will be generated if the index parameter is greater than or equal to GL_MAX_VERTEX_ATTRIBS glEnableVertexAttribArray(0); // Defines an array of generic vertex attribute data. Takes an index, a size specifying the number of components (in this case, floats)(has a max of 4) // The third parameter, type, can be GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, or GL_FLOAT // The fourth parameter specifies whether to normalize fixed-point data values, the fifth parameter is the stride which is the offset (in bytes) between generic vertex attributes // The fifth parameter is a pointer to the first component of the first generic vertex attribute in the array. If named buffer object is bound to GL_ARRAY_BUFFER (and it is, in this case) // then the pointer parameter is treated as a byte offset into the buffer object's data. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)8); // You'll note sizeof(VertexFormat) is our stride, because each vertex contains data that adds up to that size. // You'll also notice we offset this parameter by 8 bytes, this is because the vec3 position attribute is after the vec2 texCoord attribute. A vec2 has 2 floats, each being 4 bytes // so we offset by 4*2=8 to make sure that our first attribute is actually the position. The reason we put position after texCoord in the struct has to do with padding. // For more info on padding, Google it. // This is our texCoord attribute, so the offset is 0, and the size is 2 since there are 2 floats for texCoord. glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(VertexFormat), (void*)0); // Read in the shader code from a file. std::string vertShader = readShader("VertexShader.glsl"); std::string fragShader = readShader("FragmentShader.glsl"); // createShader consolidates all of the shader compilation code vertex_shader = createShader(vertShader, GL_VERTEX_SHADER); fragment_shader = createShader(fragShader, GL_FRAGMENT_SHADER); // A shader is a program that runs on your GPU instead of your CPU. In this sense, OpenGL refers to your groups of shaders as "programs". // Using glCreateProgram creates a shader program and returns a GLuint reference to it. program = glCreateProgram(); glAttachShader(program, vertex_shader); // This attaches our vertex shader to our program. glAttachShader(program, fragment_shader); // This attaches our fragment shader to our program. // This links the program, using the vertex and fragment shaders to create executables to run on the GPU. glLinkProgram(program); // End of shader and program creation glUseProgram(program); // This generates texture object names // The first parameter is the number of texture objects, and the second parameter is a pointer to an array of texture objects (yes, before this call, tex was an empty variable) // (In this example, there's only one texture object.) glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); int width, height; // Variables to store the width and height of the loaded texture. These will be empty until SOIL_load_image is called. // SOIL loads an image from the given filepath. The fourth parameter is the number of channels, and the last parameter is the format to load the data in. // This will load the data from your file into an "image", which is just a char array. unsigned char* image = SOIL_load_image("texture.png", &width, &height, 0, SOIL_LOAD_RGBA); // Using this image, we can call glTexImage2D to create a 2D texture. Parameters: target GL_TEXTURE_2D, level of detail (0 is base, x is xth mipmap reduction), internal format, // width, height, border (if we're drawing a border around the image), format of texel data (must match internal format), type of texel data, and a pointer to image data in memory. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image); // Now that we've created our texture on GL_TEXTURE_2D, we don't need the image anymore. So we free that memory using SOIL. SOIL_free_image_data(image); // Sets texture parameters, given a target, symbolic name of the texture parameter, and a value for that parameter. // Valid symbolic names are GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_WRAP_S, or GL_TEXTURE_WRAP_T. // Each has their own different set of values as well. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Generates a mipmap for the texture, and there's no reason not to. glGenerateMipmap(GL_TEXTURE_2D); // This gets us a reference to the uniform variable in the vertex shader, which is called "trans". // We're using this variable as a 4x4 transformation matrix // Only 2 parameters required: A reference to the shader program and the name of the uniform variable within the shader code. uniTrans = glGetUniformLocation(program, "trans"); // This is not necessary, but I prefer to handle my vertices in the clockwise order. glFrontFace defines which face of the triangles you're drawing is the front. // Essentially, if you draw your vertices in counter-clockwise order, by default (in OpenGL) the front face will be facing you/the screen. If you draw them clockwise, the front face // will face away from you. By passing in GL_CW to this function, we are saying the opposite, and now the front face will face you if you draw in the clockwise order. // If you don't use this, just reverse the order of the vertices in your array when you define them so that you draw the points in a counter-clockwise order. glFrontFace(GL_CW); // This is also not necessary, but more efficient and is generally good practice. By default, OpenGL will render both sides of a triangle that you draw. By enabling GL_CULL_FACE, // we are telling OpenGL to only render the front face. This means that if you rotated the triangle over the X-axis, you wouldn't see the other side of the triangle as it rotated. glEnable(GL_CULL_FACE); // Enables blending, which we will use for Alpha Blending our texture. // Basically, all color data for pixels has 4 floats, RGB is straightforward. It's just the value of Red, Green, and Blue. The fourth value is A, for Alpha. Alpha is the // transparency value, basically determining that 1.0 means it is fully visible, and 0.0 is invisible, meaning 0.5 is halfway see-through. The sample texture we are using // has transparency, so we are enabling blending to allow that transparency to be visible in our engine (otherwise, it will just be rendered black wherever it is transparent). // Note that this can have unwanted effects in other applications, and only certain file types actually include transparency (such as PNG). glEnable(GL_BLEND); // The glBlendFunc controls how the blending actually occurs. This particular setting modifies the incoming color by its alpha value, and then modifies the destination color by // one minus the alpha value of the incoming color. Then the two are summed up and displayed. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Determines the interpretation of polygons for rasterization. The first parameter, face, determines which polygons the mode applies to. // The face can be either GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK // The mode determines how the polygons will be rasterized. GL_POINT will draw points at each vertex, GL_LINE will draw lines between the vertices, and // GL_FILL will fill the area inside those lines. glPolygonMode(GL_FRONT, GL_FILL); }
// Initialization code void init() { // Initializes the glew library glewInit(); // Enables the depth test, which you will want in most cases. You can disable this in the render loop if you need to. glEnable(GL_DEPTH_TEST); // An element array, which determines which of the vertices to display in what order. This is sometimes known as an index array. GLuint elements[] = { 0, 1, 2, 0, 2, 3 }; // These are the indices for a square vertices.push_back(VertexFormat(glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(1.0f, 1.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f))); vertices.push_back(VertexFormat(glm::vec3(1.0f, -1.0f, 0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 1.0f))); // Create our square model from the data. square = new Model(vertices.size(), vertices.data(), 6, elements); // Create two GameObjects based off of the square model (note that they are both holding pointers to the square, not actual copies of the square vertex data). obj1 = new GameObject(square); obj2 = new GameObject(square); // Set beginning properties of GameObjects. obj1->SetVelocity(glm::vec3(0, 0.0f, 0.0f)); // The first object doesn't move. obj2->SetVelocity(glm::vec3(-speed, 0.0f, 0.0f)); obj1->SetPosition(glm::vec3(0.0f, 0.0f, 0.0f)); obj2->SetPosition(glm::vec3(0.7f, 0.0f, 0.0f)); obj1->SetScale(glm::vec3(0.25f, 0.25f, 0.25f)); obj2->SetScale(glm::vec3(0.05f, 0.05f, 0.05f)); // Read in the shader code from a file. std::string vertShader = readShader("VertexShader.glsl"); std::string fragShader = readShader("FragmentShader.glsl"); // createShader consolidates all of the shader compilation code vertex_shader = createShader(vertShader, GL_VERTEX_SHADER); fragment_shader = createShader(fragShader, GL_FRAGMENT_SHADER); // A shader is a program that runs on your GPU instead of your CPU. In this sense, OpenGL refers to your groups of shaders as "programs". // Using glCreateProgram creates a shader program and returns a GLuint reference to it. program = glCreateProgram(); glAttachShader(program, vertex_shader); // This attaches our vertex shader to our program. glAttachShader(program, fragment_shader); // This attaches our fragment shader to our program. // This links the program, using the vertex and fragment shaders to create executables to run on the GPU. glLinkProgram(program); // End of shader and program creation // This gets us a reference to the uniform variable in the vertex shader, which is called "MVP". // We're using this variable as a 4x4 transformation matrix // Only 2 parameters required: A reference to the shader program and the name of the uniform variable within the shader code. uniMVP = glGetUniformLocation(program, "MVP"); // Creates the view matrix using glm::lookAt. // First parameter is camera position, second parameter is point to be centered on-screen, and the third paramter is the up axis. view = glm::lookAt( glm::vec3(0.0f, 0.0f, 2.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); // Creates a projection matrix using glm::perspective. // First parameter is the vertical FoV (Field of View), second paramter is the aspect ratio, 3rd parameter is the near clipping plane, 4th parameter is the far clipping plane. proj = glm::perspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f); // Allows us to make one less calculation per frame, as long as we don't update the projection and view matrices every frame. PV = proj * view; // Create your MVP matrices based on the objects' transforms. MVP = PV * *obj1->GetTransform(); MVP2 = PV * *obj2->GetTransform(); // Calculate the Axis-Aligned Bounding Box for your object. obj1->CalculateAABB(); obj2->CalculateAABB(); // This is not necessary, but I prefer to handle my vertices in the clockwise order. glFrontFace defines which face of the triangles you're drawing is the front. // Essentially, if you draw your vertices in counter-clockwise order, by default (in OpenGL) the front face will be facing you/the screen. If you draw them clockwise, the front face // will face away from you. By passing in GL_CW to this function, we are saying the opposite, and now the front face will face you if you draw in the clockwise order. // If you don't use this, just reverse the order of the vertices in your array when you define them so that you draw the points in a counter-clockwise order. glFrontFace(GL_CW); // This is also not necessary, but more efficient and is generally good practice. By default, OpenGL will render both sides of a triangle that you draw. By enabling GL_CULL_FACE, // we are telling OpenGL to only render the front face. This means that if you rotated the triangle over the X-axis, you wouldn't see the other side of the triangle as it rotated. glEnable(GL_CULL_FACE); // Determines the interpretation of polygons for rasterization. The first parameter, face, determines which polygons the mode applies to. // The face can be either GL_FRONT, GL_BACK, or GL_FRONT_AND_BACK // The mode determines how the polygons will be rasterized. GL_POINT will draw points at each vertex, GL_LINE will draw lines between the vertices, and // GL_FILL will fill the area inside those lines. glPolygonMode(GL_FRONT, GL_FILL); }
Mesh* createGridMesh(unsigned int lineCount) { // There needs to be an odd number of lines lineCount |= 1; const unsigned int pointCount = lineCount * 4; const unsigned int verticesSize = pointCount * (3 + 3); std::vector<float> vertices; vertices.resize(verticesSize); const float gridLength = (float)(lineCount / 2); float value = -gridLength; for (unsigned int i = 0; i < verticesSize; ++i) { // Default line color is dark grey Vector4 color(0.3f, 0.3f, 0.3f, 1.0f); // Very 10th line is brighter grey if (((int)value) % 10 == 0) { color.set(0.45f, 0.45f, 0.45f, 1.0f); } // The Z axis is blue if (value == 0.0f) { color.set(0.15f, 0.15f, 0.7f, 1.0f); } // Build the lines vertices[i] = value; vertices[++i] = 0.0f; vertices[++i] = -gridLength; vertices[++i] = color.x; vertices[++i] = color.y; vertices[++i] = color.z; vertices[++i] = value; vertices[++i] = 0.0f; vertices[++i] = gridLength; vertices[++i] = color.x; vertices[++i] = color.y; vertices[++i] = color.z; // The X axis is red if (value == 0.0f) { color.set(0.7f, 0.15f, 0.15f, 1.0f); } vertices[++i] = -gridLength; vertices[++i] = 0.0f; vertices[++i] = value; vertices[++i] = color.x; vertices[++i] = color.y; vertices[++i] = color.z; vertices[++i] = gridLength; vertices[++i] = 0.0f; vertices[++i] = value; vertices[++i] = color.x; vertices[++i] = color.y; vertices[++i] = color.z; value += 1.0f; } VertexFormat::Element elements[] = { VertexFormat::Element(VertexFormat::POSITION, 3), VertexFormat::Element(VertexFormat::COLOR, 3) }; Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), pointCount, false); if (mesh == NULL) { return NULL; } mesh->setPrimitiveType(Mesh::LINES); mesh->setVertexData(&vertices[0], 0, pointCount); return mesh; }
void Mesh::Deserialize(Deserializer &deserializer) { Serialization::ChunkHeader header; do { deserializer.Read(header); switch (header.id) { case Serialization::ChunkID_Mesh_Material: { switch (header.version) { case 1: { String materialPath; deserializer.ReadString(materialPath); this->SetMaterial(materialPath.c_str()); this->material->Deserialize(deserializer); break; } default: { m_context.Logf("Error deserializing Mesh. Material chunk is an unsupported version (%d).", header.version); break; } } break; } case Serialization::ChunkID_Mesh_Geometry: { switch (header.version) { case 1: { if (this->deleteGeometry) { Renderer::DeleteVertexArray(this->geometry); } auto newVA = Renderer::CreateVertexArray(VertexArrayUsage_Static, VertexFormat()); newVA->Deserialize(deserializer); this->SetGeometry(newVA); this->deleteGeometry = true; break; } default: { m_context.Logf("Error deserializing Mesh. Geometry chunk is an unsupported version (%d).", header.version); break; } } break; } default: { // We're not aware of the chunk, so we'll skip it. deserializer.Seek(header.sizeInBytes); break; } } } while (header.id != Serialization::ChunkID_Null); }
InputLayoutManager::InputLayoutManager(void) { for (VertexFormat index = VertexFormat(0); index < eVERTEX_MAX; index = VertexFormat(index + 1)) inputLayouts[index] = 0; }
#include "mesh.h" #include "engine.h" #include "util.h" #include <fstream> #include <algorithm> bool Vertex::FormatInitialized = false; VertexFormat Vertex::Format = VertexFormat(); std::map<std::string, Mesh*> Mesh::Meshes = std::map<std::string, Mesh*>(); Mesh* Mesh::Get(const std::string& name) { std::map<std::string, Mesh*>::iterator it = Meshes.find(name); if(it != Meshes.end()) return it->second; Meshes.insert(std::pair<std::string, Mesh*>(name, new Mesh(name))); return Meshes.at(name); } Mesh* Mesh::Create(const std::string& name, Vertex* vertices, int nVertices, INDEX* indices, int nIndices, bool calcNormals, bool calcTangents, const VertexFormat& vertexFormat) { if(Meshes.find(name) != Meshes.end()) Engine::GetDisplay()->Error("Mesh " + name + " already exists, and therefore cannot be created."); Meshes.insert(std::pair<std::string, Mesh*>(name, new Mesh(vertices, nVertices, indices, nIndices, calcNormals, calcTangents, vertexFormat))); return Meshes.at(name); }
void Cuboid::create(GLfloat sizeX, GLfloat sizeY, GLfloat sizeZ, const glm::vec4& color) { // Vertices std::vector<VertexFormat> vertices; glm::vec3 normal; // Front face normal = glm::vec3(0.0, 0.0, 1.0); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Right face normal = glm::vec3(1.0, 0.0, 0.0); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Back face normal = glm::vec3(0.0, 0.0, -1.0); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Left face normal = glm::vec3(-1.0, 0.0, 0.0); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Top face normal = glm::vec3(0.0, 1.0, 0.0); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Bottom face normal = glm::vec3(0.0, -1.0, 0.0); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(0, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, -sizeZ * 0.5f), normal, glm::vec2(1, 0), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(1, 1), glm::vec4(color))); vertices.push_back(VertexFormat(glm::vec3(-sizeX * 0.5f, -sizeY * 0.5f, sizeZ * 0.5f), normal, glm::vec2(0, 1), glm::vec4(color))); // Indices std::vector<GLuint> indices = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23 }; GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(VertexFormat), &vertices[0], GL_STATIC_DRAW); GLuint ibo; glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW); setAttribPointers(); this->vao = vao; this->vbos.push_back(vbo); this->vbos.push_back(ibo); }