//----------------------------------------------------------------------- void LightInstanceBatchHW::removeBlendData() { VertexData *thisVertexData = mRenderOperation.vertexData; unsigned short safeSource = 0xFFFF; const VertexElement* blendIndexElem = thisVertexData->vertexDeclaration->findElementBySemantic( VES_BLEND_INDICES ); if( blendIndexElem ) { //save the source in order to prevent the next stage from unbinding it. safeSource = blendIndexElem->getSource(); // Remove buffer reference thisVertexData->vertexBufferBinding->unsetBinding( blendIndexElem->getSource() ); } // Remove blend weights const VertexElement* blendWeightElem = thisVertexData->vertexDeclaration->findElementBySemantic( VES_BLEND_WEIGHTS ); if( blendWeightElem && blendWeightElem->getSource() != safeSource ) { // Remove buffer reference thisVertexData->vertexBufferBinding->unsetBinding( blendWeightElem->getSource() ); } thisVertexData->vertexDeclaration->removeElement(VES_BLEND_INDICES); thisVertexData->vertexDeclaration->removeElement(VES_BLEND_WEIGHTS); thisVertexData->closeGapsInBindings(); }
/* Functions extracted out of readFromFile to enhance readability. */ bool VertexBufferRoot::_constructFromPly( const std::string& filename ) { PLYLIBINFO << "Reading PLY file." << std::endl; boost::progress_display progress( 12 ); VertexData data; if( _invertFaces ) data.useInvertedFaces(); if( !data.readPlyFile( filename ) ) { PLYLIBERROR << "Unable to load PLY file." << std::endl; return false; } ++progress; data.calculateNormals(); data.scale( 2.0f ); ++progress; setupTree( data, progress ); ++progress; if( !writeToFile( filename )) PLYLIBWARN << "Unable to write binary representation." << std::endl; ++progress; return true; }
void HEC_FromFaceList::copyFromVertexData(VertexData& vd) { for(int i = 0; i < vd.getNumVertices(); ++i) { addVertex(vd.getVertex(i)); } for(int i = 0; i < vd.getNumQuads(); ++i) { Quad& q = *vd.getQuadPtr(i); addQuad(q.a, q.b, q.c, q.d); } }
NS_CC_BEGIN VertexData* VertexData::create() { VertexData* result = new (std::nothrow) VertexData(); if(result) { result->autorelease(); return result; } CC_SAFE_DELETE(result); return nullptr; }
void loadObj(const std::string &filename, VertexData &vd, IndexedFaceMesh &mesh, const Vector3r &scale) { std::vector<OBJLoader::Vec3f> x; std::vector<OBJLoader::Vec3f> normals; std::vector<OBJLoader::Vec2f> texCoords; std::vector<MeshFaceIndices> faces; OBJLoader::Vec3f s = { (float)scale[0], (float)scale[1], (float)scale[2] }; OBJLoader::loadObj(filename, &x, &faces, &normals, &texCoords, s); mesh.release(); const unsigned int nPoints = (unsigned int)x.size(); const unsigned int nFaces = (unsigned int)faces.size(); const unsigned int nTexCoords = (unsigned int)texCoords.size(); mesh.initMesh(nPoints, nFaces * 2, nFaces); vd.reserve(nPoints); for (unsigned int i = 0; i < nPoints; i++) { vd.addVertex(Vector3r(x[i][0], x[i][1], x[i][2])); } for (unsigned int i = 0; i < nTexCoords; i++) { mesh.addUV(texCoords[i][0], texCoords[i][1]); } for (unsigned int i = 0; i < nFaces; i++) { // Reduce the indices by one int posIndices[3]; int texIndices[3]; for (int j = 0; j < 3; j++) { posIndices[j] = faces[i].posIndices[j] - 1; if (nTexCoords > 0) { texIndices[j] = faces[i].texIndices[j] - 1; mesh.addUVIndex(texIndices[j]); } } mesh.addFace(&posIndices[0]); } mesh.buildNeighbors(); mesh.updateNormals(vd, 0); mesh.updateVertexNormals(vd); LOG_INFO << "Number of triangles: " << nFaces; LOG_INFO << "Number of vertices: " << nPoints; }
/* Begin kd-tree setup, go through full range starting with x axis. */ void VertexBufferRoot::setupTree( VertexData& data ) { // data is VertexData, _data is VertexBufferData _data.clear(); const Axis axis = data.getLongestAxis( 0, data.triangles.size() ); VertexBufferNode::setupTree( data, 0, data.triangles.size(), axis, 0, _data ); VertexBufferNode::updateBoundingSphere(); VertexBufferNode::updateRange(); #if 0 // re-test all points to be in the bounding sphere Vertex center( _boundingSphere.array ); float radius = _boundingSphere.w(); float radiusSquared = radius * radius; for( size_t offset = 0; offset < _data.vertices.size(); ++offset ) { const Vertex& vertex = _data.vertices[ offset ]; const Vertex centerToPoint = vertex - center; const float distanceSquared = centerToPoint.squared_length(); EQASSERTINFO( distanceSquared <= radiusSquared, distanceSquared << " > " << radiusSquared ); } #endif }
void send_attribute(ShaderAvailableAttributes attr, const VertexData& data, EnabledMethod exists_on_data_predicate, OffsetMethod offset_func) { int32_t loc = (int32_t) attr; auto get_has_attribute = std::bind(exists_on_data_predicate, std::reference_wrapper<const VertexData>(data)); if(get_has_attribute()) { auto get_offset = std::bind(offset_func, std::reference_wrapper<const VertexData>(data)); GLCheck(glEnableVertexAttribArray, loc); GLCheck(glVertexAttribPointer, loc, SHADER_ATTRIBUTE_SIZES.find(attr)->second, GL_FLOAT, GL_FALSE, data.stride(), BUFFER_OFFSET(get_offset()) ); } else { //L_WARN_ONCE(_u("Couldn't locate attribute on the mesh: {0}").format(attr)); } }
/* Continue kd-tree setup, create intermediary or leaf nodes as required. */ void VertexBufferNode::setupTree( VertexData& data, const Index start, const Index length, const Axis axis, const size_t depth, VertexBufferData& globalData, boost::progress_display& progress ) { data.sort( start, length, axis ); const Index median = start + ( length / 2 ); // left child will include elements smaller than the median const Index leftLength = length / 2; const bool subdivideLeft = _subdivide( leftLength, depth ); if( subdivideLeft ) _left = new VertexBufferNode; else _left = new VertexBufferLeaf( globalData ); // right child will include elements equal to or greater than the median const Index rightLength = ( length + 1 ) / 2; const bool subdivideRight = _subdivide( rightLength, depth ); if( subdivideRight ) _right = new VertexBufferNode; else _right = new VertexBufferLeaf( globalData ); // move to next axis and continue contruction in the child nodes const Axis newAxisLeft = subdivideLeft ? data.getLongestAxis( start , leftLength ) : AXIS_X; const Axis newAxisRight = subdivideRight ? data.getLongestAxis( median, rightLength ) : AXIS_X; static_cast< VertexBufferNode* > ( _left )->setupTree( data, start, leftLength, newAxisLeft, depth+1, globalData, progress ); static_cast< VertexBufferNode* > ( _right )->setupTree( data, median, rightLength, newAxisRight, depth+1, globalData, progress ); if( depth == 3 ) ++progress; }
Sphere::Sphere( bool fullSphere, byte numSubDiv, float dim ) { setPrimitiveType( PrimitiveType::Triangles ); VertexData position; buildGeometry( fullSphere, numSubDiv, position, dim ); // Build Texture Coordinates. BoundingBox box; for( size_t i = 0; i < position.size(); i++ ) { const Vector3& v = position[i]; box.add(v); } Vector3 center = box.getCenter(); std::vector<Vector3> texCoords; for( size_t i = 0; i < position.size(); i++ ) { const Vector3& vert = position[i]; Vector3 d = vert-center; d.normalize(); // Conveert to spherical coordinates. //float t = d.z / sqrt(d.x*d.x+d.y*d.y+d.z*d.z); //float delta = acos(t); //float phi = atan2(d.y, d.x); //float u = delta / Math::PI; //float v = phi / 2*Math::PI; float u = std::asin(d.x) / PI + 0.5f; float v = std::asin(d.y) / PI + 0.5f; texCoords.push_back( Vector2(u, v) ); } gb->set( VertexAttribute::Position, position ); gb->set( VertexAttribute::TexCoord0, texCoords ); }
/* Functions extracted out of readFromFile to enhance readability. */ bool VertexBufferRoot::_constructFromPly( const std::string& filename ) { MESHINFO << "Constructing new from PLY file." << std::endl; VertexData data; if( _invertFaces ) data.useInvertedFaces(); if( !data.readPlyFile( filename ) ) { MESHERROR << "Unable to load PLY file." << std::endl; return false; } data.calculateNormals(); data.scale( 2.0f ); setupTree( data ); if( !writeToFile( filename )) MESHWARN << "Unable to write binary representation." << std::endl; return true; }
void Sphere::subdivide(const Vector3& v1, const Vector3& v2, const Vector3& v3, byte depth, VertexData& pos) { if (depth == 0) { pos.push_back( v1 ); pos.push_back( v2 ); pos.push_back( v3 ); return; } Vector3 v12 = (v1+v2).normalize(); Vector3 v23 = (v2+v3).normalize(); Vector3 v31 = (v3+v1).normalize(); subdivide(v1, v12, v31, depth-1, pos); subdivide(v2, v23, v12, depth-1, pos); subdivide(v3, v31, v23, depth-1, pos); subdivide(v12, v23, v31, depth-1, pos); }
/* Begin kd-tree setup, go through full range starting with x axis. */ void VertexBufferRoot::setupTree( VertexData& data, boost::progress_display& progress ) { // data is VertexData, _data is VertexBufferData _data.clear(); const Axis axis = data.getLongestAxis( 0, data.triangles.size() ); VertexBufferNode::setupTree( data, 0, data.triangles.size(), axis, 0, _data, progress ); VertexBufferNode::updateBoundingSphere(); VertexBufferNode::updateRange(); }
void Sphere::buildGeometry( bool fullSphere, byte numSubDiv, VertexData& pos, float dim) { GeometryBufferPtr gb = AllocateThis(GeometryBuffer); setGeometryBuffer(gb); // Rotate the vertices, else the sphere is not properly aligned. Matrix4x3 rot = Matrix4x3::createRotation( EulerAngles(-60, 0, 0) ); for( size_t i = 0; i < ARRAY_SIZE(IcoDomeIndices); i++ ) { const byte* p = IcoDomeIndices[i]; Vector3 v1( IcoVertices[p[0]][0], IcoVertices[p[0]][2], IcoVertices[p[0]][1] ); Vector3 v2( IcoVertices[p[1]][0], IcoVertices[p[1]][2], IcoVertices[p[1]][1] ); Vector3 v3( IcoVertices[p[2]][0], IcoVertices[p[2]][2], IcoVertices[p[2]][1] ); subdivide( rot*v1, rot*v2, rot*v3, numSubDiv, pos ); } // If we don't want a full sphere, we return here. if( fullSphere ) { // These indices are the bottom of the sphere. for( size_t i = 0; i < ARRAY_SIZE(IcoSphereIndices); i++ ) { const byte* p = IcoSphereIndices[i]; Vector3 v1( IcoVertices[p[0]][0], IcoVertices[p[0]][2], IcoVertices[p[0]][1] ); Vector3 v2( IcoVertices[p[1]][0], IcoVertices[p[1]][2], IcoVertices[p[1]][1] ); Vector3 v3( IcoVertices[p[2]][0], IcoVertices[p[2]][2], IcoVertices[p[2]][1] ); subdivide( rot*v1, rot*v2, rot*v3, numSubDiv, pos ); } } // Scale all the vertices. for( size_t i = 0; i < pos.size(); i++ ) { Vector3& vec = pos[i]; vec *= dim; } }
/* Finish partial setup - sort, reindex and merge into global data. */ void VertexBufferLeaf::setupTree( VertexData& data, const Index start, const Index length, const Axis axis, const size_t depth, VertexBufferData& globalData ) { data.sort( start, length, axis ); _vertexStart = globalData.vertices.size(); _vertexLength = 0; _indexStart = globalData.indices.size(); _indexLength = 0; const bool hasColors = ( data.colors.size() > 0 ); // stores the new indices (relative to _start) map< Index, ShortIndex > newIndex; for( Index t = 0; t < length; ++t ) { for( Index v = 0; v < 3; ++v ) { Index i = data.triangles[start + t][v]; if( newIndex.find( i ) == newIndex.end() ) { newIndex[i] = _vertexLength++; // assert number of vertices does not exceed SmallIndex range MESHASSERT( _vertexLength ); globalData.vertices.push_back( data.vertices[i] ); if( hasColors ) globalData.colors.push_back( data.colors[i] ); globalData.normals.push_back( data.normals[i] ); } globalData.indices.push_back( newIndex[i] ); ++_indexLength; } } #ifndef NDEBUG MESHINFO << "VertexBufferLeaf::setupTree" << "( " << _indexStart << ", " << _indexLength << "; start " << _vertexStart << ", " << _vertexLength << " vertices)." << endl; #endif }
void VertexBuffer::alloc(const VertexData &data, GpuBufferUsageType usage) { assert(data.getFormat() == m_format); alloc(data.getVerticesCount(), data.getRawData(), usage); }
// @todo templetize void Box::create(float width, float height, float depth, VertexData& vd) { float x = width * 0.5; float y = height * 0.5; float z = depth * 0.5; // back // ------------------- vd.addVertex(x,-y,-z); vd.addVertex(-x,-y,-z); vd.addVertex(-x,y,-z); vd.addVertex(x,y,-z); // vd.addVertex(-x,-y,-z); // vd.addVertex(-x, y,-z); // vd.addVertex(x,y,-z); // vd.addVertex(x,-y,-z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(0,0,-1); vd.addNormal(0,0,-1); vd.addNormal(0,0,-1); vd.addNormal(0,0,-1); vd.addQuad(0,1,2,3); // left // ------------------- vd.addVertex(-x, -y, -z); vd.addVertex(-x, -y, z); vd.addVertex(-x, y, z); vd.addVertex(-x, y, -z); // vd.addVertex(-x, -y, -z); // vd.addVertex(-x, -y, z); // vd.addVertex(-x, y, z); // vd.addVertex(-x, y, -z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(-1,0,0); vd.addNormal(-1,0,0); vd.addNormal(-1,0,0); vd.addNormal(-1,0,0); vd.addQuad(4,5,6,7); // right // ------------------- vd.addVertex(x, -y, z); vd.addVertex(x, -y, -z); vd.addVertex(x, y, -z); vd.addVertex(x, y, z); // vd.addVertex(x, -y, -z); // vd.addVertex(x, -y, z); // vd.addVertex(x, y, z); // vd.addVertex(x, y, -z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(1,0,0); vd.addNormal(1,0,0); vd.addNormal(1,0,0); vd.addNormal(1,0,0); vd.addQuad(8,9,10,11); // front // ------------------- vd.addVertex(-x, -y, z); vd.addVertex(x, -y, z); vd.addVertex(x, y, z); vd.addVertex(-x, y, z); // vd.addVertex(-x, -y, z); // vd.addVertex(-x, y, z); // vd.addVertex(x, y, z); // vd.addVertex(x, -y, z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(0,0,1); vd.addNormal(0,0,1); vd.addNormal(0,0,1); vd.addNormal(0,0,1); vd.addQuad(12,13,14,15); // bottom // ------------------- vd.addVertex(-x, -y, -z); vd.addVertex(-x, -y, z); vd.addVertex(x, -y, z); vd.addVertex(x, -y, -z); // vd.addVertex(-x, -y, z); // vd.addVertex(x, -y, z); // vd.addVertex(x, -y, -z); // vd.addVertex(-x, -y, -z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(0,-1,0); vd.addNormal(0,-1,0); vd.addNormal(0,-1,0); vd.addNormal(0,-1,0); vd.addQuad(16,17,18,19); // top // ------------------- vd.addVertex(-x, y, z); vd.addVertex(x, y, z); vd.addVertex(x, y, -z); vd.addVertex(-x, y, -z); // vd.addVertex(-x, y, -z); // vd.addVertex(-x, y, z); // vd.addVertex(x, y, z); // vd.addVertex(x, y, -z); vd.addTexCoord(0,0); vd.addTexCoord(1,0); vd.addTexCoord(1,1); vd.addTexCoord(0,1); vd.addNormal(0,1,0); vd.addNormal(0,1,0); vd.addNormal(0,1,0); vd.addNormal(0,1,0); vd.addQuad(20,21,22,23); }
void UVSphere::create(float radius, int numSlices, int numStacks, VertexData& vertex_data) { slices = numSlices; stacks = numStacks; // this code works; though as with all 4 other tested methods I get a wierd // lines when using a texture. See git history for old code. for (int j = 0; j < stacks; j++) { double latitude1 = (PI/stacks) * j - PI/2; double latitude2 = (PI/stacks) * (j+1) -PI/2; double sin1 = sin(latitude1); double cos1 = cos(latitude1); double sin2 = sin(latitude2); double cos2 = cos(latitude2); for (int i = 0; i <= slices; i++) { double longitude = (2*PI/slices) * i; double sin_long = sin(longitude); double cos_long = cos(longitude); double x1 = cos_long * cos1; double y1 = sin_long * cos1; double z1 = sin1; double x2 = cos_long * cos2; double y2 = sin_long * cos2; double z2 = sin2; vertex_data.addVertex(Vec3(x1 * radius, y1*radius, z1 * radius)); vertex_data.addTexCoord(1-1.0/slices * i, 1.0/stacks * j); vertex_data.addNormal(Vec3(x1, y1, z1)); vertex_data.addVertex(Vec3(x2 * radius, y2*radius, z2 * radius)); vertex_data.addTexCoord(1-1.0/slices * i, 1.0/stacks * (j+1)); vertex_data.addNormal(Vec3(x2, y2, z2)); } } int n = vertex_data.getNumVertices(); for(int i = 0; i < n-2; i+=2) { vertex_data.addQuad(i+1, i+3, i+2, i); } /* int nv = stacks; int nu = slices; vector<Vec3> vertices; vector<Vec2> texcoords; vertices.push_back(Vec3(0,0,radius)); vertices.push_back(Vec3(0,0,-radius)); for(int i = 0; i < stacks; ++i) { float t = i / (float) stacks; float sin_v = sin(TWO_PI * t); float cos_v = cos(TWO_PI * t); for(int j = 1; j < slices; ++j) { float s = j / (float) slices; float sin_u = sin(PI * s); float cos_u = cos(PI * s); vertices.push_back(Vec3( cos_v * sin_u * radius ,sin_v * sin_u * radius ,cos_u * radius )); texcoords.push_back(Vec2(s,t)); } } vector<int> indices; for(int k = 0; k < nv; ++k) { indices.push_back(0); indices.push_back(2 + k * (nu - 1)); indices.push_back(2 + ((k + 1) % nv) * (nu - 1)); indices.push_back(1); indices.push_back(((k + 1) % nv) * (nu - 1) + nu); indices.push_back(k * (nu - 1) + nu); for(int l = 0; l < (nu-2); ++l) { indices.push_back(2 + k * (nu - 1) + l); indices.push_back(2 + k * (nu - 1) + l + 1); indices.push_back( 2 + ((k + 1) % nv) * (nu - 1) + l); indices.push_back(2 + k * (nu - 1) + l + 1); indices.push_back(2 + ((k + 1) % nv) * (nu - 1) + l + 1); indices.push_back(2 + ((k + 1) % nv) * (nu - 1) + l); } } for(int i = 0; i < indices.size(); ++i) { vertex_data.addVertex(vertices[indices[i]]); vertex_data.addTexCoord(texcoords[indices[i]]); } printf("Num indices: %d\n", indices.size()); */ /* int num_vertices = (stacks + 1) * (slices + 1); vector<Vec3>vertices; vector<Vec2>texcoords; vertices.assign(num_vertices, Vec3()); texcoords.assign(num_vertices, Vec2()); // calculate vertex + texcoords for(float stack = 0; stack <= stacks; ++stack) { float theta = stack/(stacks) * PI; float sin_theta = sinf(theta); float cos_theta = cosf(theta); for(float slice = 0; slice <= slices; ++slice) { float phi = slice/(slices) * TWO_PI; float sin_phi = sinf(phi); float cos_phi = cosf(phi); float x = sin_theta * cos_phi; float y = sin_theta * sin_phi; float z = cos_theta; float u = (sin_theta * cos_phi * 0.5) + 0.5; float v = (sin_theta * sin_phi * 0.5) + 0.5; int index = (int)(slice + (stack * (slices+1))); vertices[index].set(x * radius,y * radius, z * radius); texcoords[index].set(u,v); } } // Create the quads int dx = 0; int num_index_elements = (stacks) * (slices) * 4; num_index_elements = (stacks) * (slices) * 4; int* index_elements = new int[num_index_elements]; for(int i = 0; i < slices; ++i) { for(int j = 0; j < stacks; ++j) { index_elements[dx++] = getAt(i,j); index_elements[dx++] = getAt(i+1,j); index_elements[dx++] = getAt(i+1,j+1); index_elements[dx++] = getAt(i,j+1); } } for(int i = 0; i < num_index_elements;++i) { Vec3 v = vertices[index_elements[i]]; vertex_data.addVertex(v); vertex_data.addTexCoord(texcoords[index_elements[i]]); } */ }
Element::Element(VertexData vertex_data, std::shared_ptr<Skin> skin, const unsigned int layer) : Renderable(vertex_data.generateVertexArrayObject(), vertex_data), skin(skin), anchor_point(glm::vec2(0.0, 0.0)), width(0), height(0), text_padding(0), cursor_within(false), color(glm::vec4(1.0)), layer(layer) { setShader(skin->getShader()); addTexture(0, "skin0", skin->getTexture()); getTransform()->translate(glm::vec3(0.0, 0.0, -(float)layer)); }
void IcoSphere::create(int detail, float radius, VertexData& vertex_data) { // how we got these values: // http://www.bobchapman.co.uk/The_Geometry_of_the_Singapore_Ball.pdf float x = 0.525731112119133606; float z = 0.850650808352039932; // default icosahedron vector<Vec3> tmp_verts; tmp_verts.push_back(Vec3( -x, 0, z )); tmp_verts.push_back(Vec3( x, 0, z )); tmp_verts.push_back(Vec3( -x, 0, -z )); tmp_verts.push_back(Vec3( x, 0, -z )); tmp_verts.push_back(Vec3( 0, z, x )); tmp_verts.push_back(Vec3( 0, z, -x )); tmp_verts.push_back(Vec3( 0, -z, x )); tmp_verts.push_back(Vec3( 0, -z, -z )); tmp_verts.push_back(Vec3( z, x, 0 )); tmp_verts.push_back(Vec3( -z, x, 0 )); tmp_verts.push_back(Vec3( z, -x, 0 )); tmp_verts.push_back(Vec3( -z, -x, 0 )); // triangle indices int idxs[] = { 1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, 1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2, 3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0, 10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7 }; int num = 4 * 5 * 3; for(int i = 0; i < num; ++i) { vertex_data.indices.push_back(idxs[i]); } if(detail > 8) { detail = 8; } else if (detail < 0) { detail = 0; } // iterator over the number of detail level and for(int i = 0; i < detail; ++i) { vector<int> indices2; vector<Vec3> tmp_verts2; for(int j = 0, idx = 0; j < vertex_data.indices.size(); j+=3) { // add triangle indices indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); // split triangle. Vec3 v1 = tmp_verts[vertex_data.indices[j+0]]; Vec3 v2 = tmp_verts[vertex_data.indices[j+1]]; Vec3 v3 = tmp_verts[vertex_data.indices[j+2]]; v1.normalize(); v2.normalize(); v3.normalize(); Vec3 a = (v1 + v2) * 0.5f; Vec3 b = (v2 + v3) * 0.5f; Vec3 c = (v3 + v1) * 0.5f; a.normalize(); b.normalize(); c.normalize(); tmp_verts2.push_back(v1); tmp_verts2.push_back(a); tmp_verts2.push_back(c); tmp_verts2.push_back(a); tmp_verts2.push_back(v2); tmp_verts2.push_back(b); tmp_verts2.push_back(a); tmp_verts2.push_back(b); tmp_verts2.push_back(c); tmp_verts2.push_back(c); tmp_verts2.push_back(b); tmp_verts2.push_back(v3); } tmp_verts = tmp_verts2; vertex_data.indices = indices2; } vector<Vec3>::iterator it = tmp_verts.begin(); while(it != tmp_verts.end()) { vertex_data.addVertex((*it) * radius); ++it; } // add the triangles size_t len = vertex_data.indices.size(); for(int i = 0; i < len; i += 3) { vertex_data.addTriangle( vertex_data.indices[i] ,vertex_data.indices[i+1] ,vertex_data.indices[i+2] ); } }