Example #1
0
// 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();
	}
}