kick
|
00001 // 00002 // mesh.cpp 00003 // KickCPP 00004 // 00005 // Created by Morten Nobel-Jørgensen on 07/12/13. 00006 // Copyright (c) 2013 Morten Nobel-Joergensen. All rights reserved. 00007 // 00008 00009 #include "kick/mesh/mesh.h" 00010 #include "kick/mesh/mesh_data.h" 00011 #include "kick/core/debug.h" 00012 #include <vector> 00013 #include <set> 00014 00015 using namespace std; 00016 00017 namespace kick { 00018 Mesh::Mesh() 00019 { 00020 glGenBuffers(1, &mVertexBufferId); 00021 glGenBuffers(1, &mElementBufferId); 00022 } 00023 00024 Mesh::~Mesh(){ 00025 if (mVertexArrayObject.size()>0){ 00026 vector<GLuint> array(mVertexArrayObject.size()); 00027 for (auto keyValue : mVertexArrayObject){ 00028 array.push_back(keyValue.second); 00029 } 00030 #ifndef GL_ES_VERSION_2_0 00031 if (openglUsingVao()) { 00032 glDeleteVertexArrays((GLsizei) array.size(), array.data()); 00033 } 00034 #endif 00035 } 00036 glDeleteBuffers(1, &mVertexBufferId); 00037 glDeleteBuffers(1, &mElementBufferId); 00038 } 00039 00040 void Mesh::bind(Shader * shader){ 00041 shader->bind(); 00042 00043 #ifndef GL_ES_VERSION_2_0 00044 if (openglUsingVao()){ 00045 auto iter = mVertexArrayObject.find(shader); 00046 if (iter == mVertexArrayObject.end()){ 00047 // create and bind object 00048 GLuint vertexArrayObjectIdx; 00049 00050 glGenVertexArrays(1, &vertexArrayObjectIdx); 00051 glBindVertexArray(vertexArrayObjectIdx); 00052 updateArrayBufferStructure(shader); 00053 mVertexArrayObject[shader] = vertexArrayObjectIdx; 00054 } else { 00055 GLuint vertexArrayObject = iter->second; 00056 glBindVertexArray(vertexArrayObject); 00057 } 00058 } else 00059 #endif 00060 { 00061 updateArrayBufferStructure(shader); 00062 } 00063 // reassign buffers 00064 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBufferId); 00065 } 00066 00067 void Mesh::updateArrayBufferStructure(Shader *shader){ 00068 glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId); 00069 static int maxAtrrSizes = -1; 00070 if (maxAtrrSizes == -1){ 00071 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAtrrSizes); 00072 if (maxAtrrSizes>32){ 00073 maxAtrrSizes = 32; 00074 } 00075 } 00076 bitset<32> enabledArrays; 00077 00078 for (InterleavedRecord format_record : mInterleavedFormat) { 00079 const AttributeDescriptor * desc = shader->getShaderAttribute(format_record.semantic); 00080 if (desc){ 00081 glEnableVertexAttribArray(desc->index); 00082 glVertexAttribPointer(desc->index, format_record.size, 00083 format_record.type, (GLboolean) format_record.normalized, format_record.stride, format_record.offset); 00084 enabledArrays[desc->index] = true; 00085 } 00086 } 00087 for (int i=0;i<maxAtrrSizes;i++){ 00088 if (enabledArrays[i] == false){ 00089 glDisableVertexAttribArray(i); 00090 } 00091 } 00092 } 00093 00094 void Mesh::render(unsigned int submeshIndex){ 00095 if (submeshIndex >= mSubmeshData.size()){ 00096 logWarning("submesh not found"); 00097 return; 00098 } 00099 auto data = mSubmeshData[submeshIndex]; 00100 GLenum mode = data.mode; 00101 GLsizei count = data.indexCount; 00102 GLenum type = data.type; 00103 const GLvoid * offset = data.dataOffset; 00104 00105 if (count < 0) { 00106 glDrawArrays(mode, 0, -count); 00107 } else if (count > 0) { 00108 glDrawElements(mode, count, type, offset); 00109 } 00110 } 00111 00112 std::string Mesh::name(){ 00113 return mName; 00114 } 00115 00116 void Mesh::setName(std::string n){ 00117 mName = n; 00118 } 00119 00120 void Mesh::setMeshData(shared_ptr<MeshData> m){ 00121 if (m != nullptr){ 00122 mInterleavedFormat = m->interleavedFormat(); 00123 mSubmeshData = m->indicesFormat(); 00124 updateMeshData(m.get()); 00125 } else { 00126 mInterleavedFormat.clear(); 00127 } 00128 mMeshData = m; 00129 } 00130 00131 void Mesh::updateMeshData(MeshData *mesh_data){ 00132 vector<float> data = mesh_data->interleavedData(); 00133 00134 if (data.size()){ 00135 GLsizeiptr vertexDataSize =data.size()*sizeof(float); 00136 glBindBuffer(GL_ARRAY_BUFFER, mVertexBufferId); 00137 glBufferData(GL_ARRAY_BUFFER, vertexDataSize, data.data(), mesh_data->meshUsageVal()); 00138 } 00139 00140 vector<GLushort> indices = mesh_data->indicesConcat(); 00141 if (indices.size()){ 00142 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBufferId); 00143 GLsizeiptr indicesSize = indices.size()*sizeof(GLushort); 00144 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesSize, indices.data(), mesh_data->meshUsageVal()); 00145 } 00146 } 00147 00148 std::shared_ptr<MeshData> Mesh::meshData() { 00149 return mMeshData; 00150 } 00151 };