void setupScene_MultiDrawElements() { ref<Geometry> torus1 = vl::makeTorus( vec3(-10, -9, 0), 8.0f, 1.0f, 20, 20 ); ref<Geometry> torus2 = vl::makeTorus( vec3( 0, -9, 0), 8.0f, 2.0f, 10, 10 ); ref<Geometry> torus3 = vl::makeTorus( vec3(+10, -9, 0), 8.0f, 3.0f, 7, 7 ); // merge vertices ref<ArrayFloat3> vert = new ArrayFloat3; ref<ArrayFloat3> torus1_vert = vl::cast<ArrayFloat3>(torus1->vertexArray()); ref<ArrayFloat3> torus2_vert = vl::cast<ArrayFloat3>(torus2->vertexArray()); ref<ArrayFloat3> torus3_vert = vl::cast<ArrayFloat3>(torus3->vertexArray()); vert->resize( torus1_vert->size() + torus2_vert->size() + torus3_vert->size() ); memcpy( vert->ptr(), torus1_vert->ptr(), torus1_vert->bytesUsed() ); memcpy( vert->ptr() + torus1_vert->bytesUsed(), torus2_vert->ptr(), torus2_vert->bytesUsed() ); memcpy( vert->ptr() + torus1_vert->bytesUsed() + torus2_vert->bytesUsed(), torus3_vert->ptr(), torus3_vert->bytesUsed() ); // merge indices ref<MultiDrawElementsUInt> mde = new MultiDrawElementsUInt(PT_QUADS); ref<DrawCall> torus1_dc = torus1->drawCalls()->at(0); ref<DrawCall> torus2_dc = torus2->drawCalls()->at(0); ref<DrawCall> torus3_dc = torus3->drawCalls()->at(0); int torus1_index_count = (int)torus1_dc->countIndices(); int torus2_index_count = (int)torus2_dc->countIndices(); int torus3_index_count = (int)torus3_dc->countIndices(); mde->indexBuffer()->resize( torus1_index_count + torus2_index_count + torus3_index_count ); MultiDrawElementsUInt::index_type* p_idx = mde->indexBuffer()->begin(); for( IndexIterator it = torus1_dc->indexIterator(); it.hasNext(); it.next(), ++p_idx ) *p_idx = it.index(); for( IndexIterator it = torus2_dc->indexIterator(); it.hasNext(); it.next(), ++p_idx ) *p_idx = it.index() + (int)torus1_vert->size(); for( IndexIterator it = torus3_dc->indexIterator(); it.hasNext(); it.next(), ++p_idx ) *p_idx = it.index() + (int)torus1_vert->size() + (int)torus2_vert->size(); VL_CHECK(p_idx == mde->indexBuffer()->end()); // define how many indices for each draw call GLsizei count_vector[] = { torus1_index_count, torus2_index_count, torus3_index_count }; mde->setCountVector( count_vector, 3 ); ref<Geometry> geom = new Geometry; geom->setVertexArray( vert.get() ); geom->drawCalls()->push_back( mde.get() ); // compute normals must be done after the draw calls have been added. geom->computeNormals(); ref<Effect> fx = new Effect; fx->shader()->setRenderState( new Light, 0 ); fx->shader()->enable(vl::EN_LIGHTING); fx->shader()->enable(vl::EN_DEPTH_TEST); fx->shader()->gocMaterial()->setDiffuse( vl::pink ); sceneManager()->tree()->addActor( geom.get(), fx.get(), NULL ); }
//----------------------------------------------------------------------------- void DoubleVertexRemover::removeDoubles(Geometry* geom) { mMapNewToOld.clear(); mMapOldToNew.clear(); std::vector<unsigned int> verti; verti.resize(geom->vertexArray()->size()); mMapOldToNew.resize(verti.size()); for(unsigned int i=0; i<verti.size(); ++i) { verti[i] = i; mMapOldToNew[i] = 0xFFFFFFFF; } mMapNewToOld.reserve(verti.size()); std::sort(verti.begin(), verti.end(), CompareVertex(geom)); if (verti.empty()) return; unsigned int unique_vert_idx = 0; for(unsigned i=1; i<verti.size(); ++i) { if ( !CompareVertex(geom).equals(verti[unique_vert_idx],verti[i]) ) { for(unsigned j=unique_vert_idx; j<i; ++j) mMapOldToNew[verti[j]] = mMapNewToOld.size(); mMapNewToOld.push_back(verti[unique_vert_idx]); unique_vert_idx = i; } } for(unsigned j=unique_vert_idx; j<verti.size(); ++j) { mMapOldToNew[verti[j]] = mMapNewToOld.size(); mMapNewToOld.push_back(verti[unique_vert_idx]); } // regenerate vertices geom->regenerateVertices(mMapNewToOld); // regenerate DrawCall std::vector< ref<DrawCall> > draw_cmd; for(int idraw=0; idraw<geom->drawCalls()->size(); ++idraw) draw_cmd.push_back( geom->drawCalls()->at(idraw) ); geom->drawCalls()->clear(); for(size_t idraw=0; idraw<draw_cmd.size(); ++idraw) { ref<DrawElementsUInt> tris = new DrawElementsUInt( draw_cmd[idraw]->primitiveType() ); geom->drawCalls()->push_back(tris.get()); const int idx_count = draw_cmd[idraw]->countIndices(); tris->indices()->resize(idx_count); int i=0; for(IndexIterator it = draw_cmd[idraw]->indexIterator(); !it.isEnd(); it.next(), ++i) tris->indices()->at(i) = mMapOldToNew[it.index()]; } #if 0 printf("DoubleVertexRemover = %d/%d, saved = %d, shrink=%.2f\n", (int)mMapNewToOld.size(), (int)verti.size(), (int)verti.size()-(int)mMapNewToOld.size(), (float)mMapNewToOld.size()/verti.size() ); #endif }