// a helper function to output a color for use in html std::string OutputColor(Vertex pt) { std::stringstream ss; ss << std::setfill('0') << std::setw(2) << std::hex << (int)floor(pt.r()) << std::setfill('0') << std::setw(2) << std::hex << (int)floor(pt.g()) << std::setfill('0') << std::setw(2) << std::hex << (int)floor(pt.b()); return ss.str(); }
void ProgressiveTriangleGeometry::Set(TriangleBasedGeometry& geometry) { int i; ClearAll(); max_vertex_count_ = geometry.GetMaxVertexCount(); max_triangle_count_ = geometry.GetMaxTriangleCount(); tbc::GeometryBase::SetBoundingRadius(geometry.GetBoundingRadius()); tbc::GeometryBase::SetBasicMaterialSettings(geometry.GetBasicMaterialSettings()); SetLastFrameVisible(geometry.GetLastFrameVisible()); SetTransformation(geometry.GetTransformation()); VertexList _vertex_list; TriangleList _triangle_list; VertexList org_vertex_list; TriangleList org_triangle_list; VertexSplitList vertex_split_list; bool clear_normal_data = (geometry.GetNormalData() != 0); geometry.GenerateVertexNormalData(); /* Copy vertex, uv and color data. */ for (i = 0; i < (int)geometry.GetVertexCount(); i++) { Vertex* vertex = new Vertex; vertex->x() = geometry.GetVertexData()[i * 3 + 0]; vertex->y() = geometry.GetVertexData()[i * 3 + 1]; vertex->z() = geometry.GetVertexData()[i * 3 + 2]; vertex->nx() = geometry.GetNormalData()[i * 3 + 0]; vertex->ny() = geometry.GetNormalData()[i * 3 + 1]; vertex->nz() = geometry.GetNormalData()[i * 3 + 2]; if (geometry.GetUVData() != 0) { vertex->u() = geometry.GetUVData()[i * 2 + 0]; vertex->v() = geometry.GetUVData()[i * 2 + 1]; } else { vertex->u() = 0.0f; vertex->v() = 0.0f; } if (geometry.GetColorData() != 0) { int __size = 4; if (geometry.GetColorFormat() == tbc::GeometryBase::kColorRgb) __size = 3; vertex->r() = (float)geometry.GetColorData()[i * __size + 0] / 255.0f; vertex->g() = (float)geometry.GetColorData()[i * __size + 1] / 255.0f; vertex->b() = (float)geometry.GetColorData()[i * __size + 2] / 255.0f; vertex->a() = 1.0f; if (__size == 4) { vertex->a() = (float)geometry.GetColorData()[i * __size + 3] / 255.0f; } } else { vertex->r() = 0.0f; vertex->g() = 0.0f; vertex->b() = 0.0f; vertex->a() = 1.0f; } _vertex_list.push_back(vertex); Vertex* v_copy = new Vertex(vertex); vertex->twin_ = v_copy; // Keep a copy of the original mesh. org_vertex_list.push_back(v_copy); } /* Copy triangles. */ int triangle_count = (int)geometry.GetTriangleCount(); for (i = 0; i < triangle_count; i++) { Triangle* triangle = new Triangle; Triangle* triangle2 = new Triangle; uint32 indices[4]; geometry.GetTriangleIndices(i, indices); triangle->v1_ = *ListUtil::FindByIndex(_vertex_list, indices[0]); triangle->v2_ = *ListUtil::FindByIndex(_vertex_list, indices[1]); triangle->v3_ = *ListUtil::FindByIndex(_vertex_list, indices[2]); triangle2->v1_ = *ListUtil::FindByIndex(org_vertex_list, indices[0]); triangle2->v2_ = *ListUtil::FindByIndex(org_vertex_list, indices[1]); triangle2->v3_ = *ListUtil::FindByIndex(org_vertex_list, indices[2]); _triangle_list.push_back(triangle); org_triangle_list.push_back(triangle2); } /* The main loop. */ Edge edge_to_collapse; while (!_triangle_list.empty()) { // FindEdgeToCollapse() will put the collapsing edge last in the array. FindEdgeToCollapse(org_vertex_list, org_triangle_list, _vertex_list, _triangle_list, edge_to_collapse); VertexSplit* vertex_split = new VertexSplit; vertex_split_list.push_back(vertex_split); vertex_split->vertex_to_split_ = edge_to_collapse.v2_; vertex_split->new_vertex_ = edge_to_collapse.v1_; vertex_split->num_old_triangles_ = (int)(_triangle_list.size() - edge_to_collapse.triangle_list_.size()); vertex_split->num_new_triangles_ = (int)edge_to_collapse.triangle_list_.size(); SetDeltaScalars(vertex_split->delta_scalars_, edge_to_collapse.v1_->scalars_, edge_to_collapse.v2_->scalars_); CopyAddScalars(vertex_split->pivot_scalars_, edge_to_collapse.v2_->scalars_, vertex_split->delta_scalars_); CopyScalars(edge_to_collapse.v2_->scalars_, vertex_split->pivot_scalars_); TriangleList::iterator tri_iter; for (tri_iter = edge_to_collapse.triangle_list_.begin(); tri_iter != edge_to_collapse.triangle_list_.end(); ++tri_iter) { Triangle* triangle = *tri_iter; _triangle_list.remove(triangle); vertex_split->new_triangles_.push_back(triangle); } // Setup the affected triangles. Affected triangles are those that // are sharing the vertex that will be removed. We need to change the pointer that // points at the removed vertex to point to the other vertex instead. for (tri_iter = _triangle_list.begin(); tri_iter != _triangle_list.end(); ++tri_iter) { Triangle* triangle = *tri_iter; if (triangle->HaveVertex(edge_to_collapse.v1_) == true) { vertex_split->fix_triangles_.push_back(triangle); triangle->ReplaceVertex(edge_to_collapse.v1_, vertex_split->vertex_to_split_); // If two vertices are the same. if (triangle->v1_ == triangle->v2_ || triangle->v1_ == triangle->v3_ || triangle->v2_ == triangle->v3_) { deb_assert(false); } } } // Place V2 last in the list, and remove V1 completely. _vertex_list.remove(edge_to_collapse.v1_); _vertex_list.remove(edge_to_collapse.v2_); _vertex_list.push_back(edge_to_collapse.v2_); } // End while(lVertexCount > 1) // Now we are all done calculating the vertex splits. // It's time to generate the final data. // Start with creating the lowest level mesh data. base_vertex_count_ = (int)_vertex_list.size(); base_triangle_count_ = (int)_triangle_list.size(); num_vertex_splits_ = (int)vertex_split_list.size(); current_vertex_count_ = base_vertex_count_; current_triangle_count_ = base_triangle_count_; base_vertex_data_ = new float[base_vertex_count_ * 3]; base_normal_data_ = new float[base_vertex_count_ * 3]; current_vertex_data_ = new float[(current_vertex_count_ + num_vertex_splits_) * 3]; current_normal_data_ = new float[(current_vertex_count_ + num_vertex_splits_) * 3]; if (geometry.GetUVData() != 0) { base_uv_data_ = new float[base_vertex_count_ * 2]; current_uv_data_ = new float[(current_vertex_count_ + num_vertex_splits_) * 2]; } if (geometry.GetColorData() != 0) { base_color_data_ = new float[base_vertex_count_ * 4]; current_color_data_ = new float[(current_vertex_count_ + num_vertex_splits_) * 4]; current_color_data8_ = new uint8[(current_vertex_count_ + num_vertex_splits_) * 4]; } VertexList::iterator vertex_iter; for (vertex_iter = _vertex_list.begin(), i = 0; vertex_iter != _vertex_list.end(); ++vertex_iter, ++i) { Vertex* vertex = *vertex_iter; base_vertex_data_[i * 3 + 0] = vertex->x(); base_vertex_data_[i * 3 + 1] = vertex->y(); base_vertex_data_[i * 3 + 2] = vertex->z(); current_vertex_data_[i * 3 + 0] = vertex->x(); current_vertex_data_[i * 3 + 1] = vertex->y(); current_vertex_data_[i * 3 + 2] = vertex->z(); base_normal_data_[i * 3 + 0] = vertex->nx(); base_normal_data_[i * 3 + 1] = vertex->ny(); base_normal_data_[i * 3 + 2] = vertex->nz(); current_normal_data_[i * 3 + 0] = vertex->nx(); current_normal_data_[i * 3 + 1] = vertex->ny(); current_normal_data_[i * 3 + 2] = vertex->nz(); if (geometry.GetUVData() != 0) { base_uv_data_[i * 2 + 0] = vertex->u(); base_uv_data_[i * 2 + 1] = vertex->v(); current_uv_data_[i * 2 + 0] = vertex->u(); current_uv_data_[i * 2 + 1] = vertex->v(); } if (geometry.GetColorData() != 0) { base_color_data_[i * 4 + 0] = vertex->r(); base_color_data_[i * 4 + 1] = vertex->g(); base_color_data_[i * 4 + 2] = vertex->b(); base_color_data_[i * 4 + 3] = vertex->a(); current_color_data_[i * 4 + 0] = vertex->r(); current_color_data_[i * 4 + 1] = vertex->g(); current_color_data_[i * 4 + 2] = vertex->b(); current_color_data_[i * 4 + 3] = vertex->a(); current_color_data8_[i * 4 + 0] = (uint8)(vertex->r() * 255.0f); current_color_data8_[i * 4 + 1] = (uint8)(vertex->g() * 255.0f); current_color_data8_[i * 4 + 2] = (uint8)(vertex->b() * 255.0f); current_color_data8_[i * 4 + 3] = (uint8)(vertex->a() * 255.0f); } } current_indices_ = new uint32[_triangle_list.size() * 3]; if (_triangle_list.empty() == false) { base_indices_ = new uint32[_triangle_list.size() * 3]; TriangleList::iterator tri_iter; for (tri_iter = _triangle_list.begin(), i = 0; tri_iter != _triangle_list.end(); ++tri_iter, ++i) { Triangle* triangle = *tri_iter; unsigned long index0 = ListUtil::FindIndexOf(_vertex_list, triangle->v1_); unsigned long index1 = ListUtil::FindIndexOf(_vertex_list, triangle->v2_); unsigned long index2 = ListUtil::FindIndexOf(_vertex_list, triangle->v3_); deb_assert(index0 >= 0); deb_assert(index1 >= 0); deb_assert(index2 >= 0); base_indices_[i * 3 + 0] = index0; base_indices_[i * 3 + 1] = index1; base_indices_[i * 3 + 2] = index2; current_indices_[i * 3 + 0] = index0; current_indices_[i * 3 + 1] = index1; current_indices_[i * 3 + 2] = index2; } } // Now let's create the rest of the data needed. if (vertex_split_list.size() > 0) { int vertex_index = (int)_vertex_list.size(); vertex_split_ = new VertexSplit[vertex_split_list.size()]; VertexSplitList::reverse_iterator vs_iter; for (vs_iter = vertex_split_list.rbegin(), i = 0; vs_iter != vertex_split_list.rend(); ++vs_iter, i++) { VertexSplit* vs = *vs_iter; vertex_split_[i].LightCopy(*vs); vertex_split_[i].num_new_triangles_ = (int)vs->new_triangles_.size(); vertex_split_[i].num_old_triangles_ = (int)_triangle_list.size(); vertex_split_[i].num_old_vertices_ = (int)_vertex_list.size(); vertex_split_[i].vertex_to_split_index_ = ListUtil::FindIndexOf(_vertex_list, vs->vertex_to_split_); vertex_split_[i].num_index_fixes_ = (int)vs->fix_triangles_.size(); vertex_split_[i].index_fix_ = new int[vertex_split_[i].num_index_fixes_]; vertex_split_[i].index_fix_index_ = new int[vertex_split_[i].num_index_fixes_ * 2]; // Write new vertex data. _vertex_list.push_back(vs->new_vertex_); current_vertex_data_[vertex_index * 3 + 0] = vs->new_vertex_->x(); current_vertex_data_[vertex_index * 3 + 1] = vs->new_vertex_->y(); current_vertex_data_[vertex_index * 3 + 2] = vs->new_vertex_->z(); current_normal_data_[vertex_index * 3 + 0] = vs->new_vertex_->nx(); current_normal_data_[vertex_index * 3 + 1] = vs->new_vertex_->ny(); current_normal_data_[vertex_index * 3 + 2] = vs->new_vertex_->nz(); if (geometry.GetUVData() != 0) { current_uv_data_[vertex_index * 2 + 0] = vs->new_vertex_->u(); current_uv_data_[vertex_index * 2 + 1] = vs->new_vertex_->v(); } if (geometry.GetColorData() != 0) { current_color_data_[vertex_index * 4 + 0] = vs->new_vertex_->r(); current_color_data_[vertex_index * 4 + 1] = vs->new_vertex_->g(); current_color_data_[vertex_index * 4 + 2] = vs->new_vertex_->b(); current_color_data_[vertex_index * 4 + 3] = vs->new_vertex_->a(); current_color_data8_[vertex_index * 4 + 0] = (uint8)(vs->new_vertex_->r() * 255.0f); current_color_data8_[vertex_index * 4 + 1] = (uint8)(vs->new_vertex_->g() * 255.0f); current_color_data8_[vertex_index * 4 + 2] = (uint8)(vs->new_vertex_->b() * 255.0f); current_color_data8_[vertex_index * 4 + 3] = (uint8)(vs->new_vertex_->a() * 255.0f); } vertex_index++; // Write index fixes. (Fix the "old" triangles). int j; TriangleList::iterator tri_iter; for (tri_iter = vs->fix_triangles_.begin(), j = 0; tri_iter != vs->fix_triangles_.end(); ++tri_iter, ++j) { Triangle* triangle = *tri_iter; deb_assert(triangle->vertex_index_history_.size() > 0); deb_assert(triangle->vertex_history_.size() > 0); int tri_index = ListUtil::FindIndexOf(_triangle_list, triangle); int vertex = triangle->vertex_index_history_.back(); triangle->vertex_index_history_.pop_back(); int index = tri_index * 3 + vertex; vertex_split_[i].index_fix_[j] = index; int old_value = 0; int new_value = 0; switch(vertex) { case 0: old_value = ListUtil::FindIndexOf(_vertex_list, triangle->v1_); triangle->v1_ = triangle->vertex_history_.back(); triangle->vertex_history_.pop_back(); new_value = ListUtil::FindIndexOf(_vertex_list, triangle->v1_); break; case 1: old_value = ListUtil::FindIndexOf(_vertex_list, triangle->v2_); triangle->v2_ = triangle->vertex_history_.back(); triangle->vertex_history_.pop_back(); new_value = ListUtil::FindIndexOf(_vertex_list, triangle->v2_); break; case 2: old_value = ListUtil::FindIndexOf(_vertex_list, triangle->v3_); triangle->v3_ = triangle->vertex_history_.back(); triangle->vertex_history_.pop_back(); new_value = ListUtil::FindIndexOf(_vertex_list, triangle->v3_); break; }; vertex_split_[i].index_fix_index_[j * 2 + 0] = old_value; vertex_split_[i].index_fix_index_[j * 2 + 1] = new_value; } // Write all new triangles. for (tri_iter = vs->new_triangles_.begin(); tri_iter != vs->new_triangles_.end(); ++tri_iter) { Triangle* triangle = *tri_iter; _triangle_list.push_back(triangle); int tri_index = (int)_triangle_list.size() - 1; unsigned long index0 = ListUtil::FindIndexOf(_vertex_list, triangle->v1_); unsigned long index1 = ListUtil::FindIndexOf(_vertex_list, triangle->v2_); unsigned long index2 = ListUtil::FindIndexOf(_vertex_list, triangle->v3_); current_indices_[tri_index * 3 + 0] = index0; current_indices_[tri_index * 3 + 1] = index1; current_indices_[tri_index * 3 + 2] = index2; } } } // Delete all memory allocated. ListUtil::DeleteAll(_triangle_list); ListUtil::DeleteAll(_vertex_list); ListUtil::DeleteAll(vertex_split_list); if (clear_normal_data == true) { geometry.ClearVertexNormalData(); } }