⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 edittrimesh.cpp

📁 3D数学基础:图形与游戏开发书籍源码,里面有很多实用的代码,对做3D的同志很有意义
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		assert(false);
		return;
	}

	// Scan triangle list and fixup vertex indices

	for (int i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);

		// Do we need to delete it?

		if (t->material == materialIndex) {
			t->mark = 1;
		} else {
			t->mark = 0;
			if (t->material > materialIndex) {
				--t->material;
			}
		}
	}

	// Delete it

	--mCount;
	memmove(&mList[materialIndex], &mList[materialIndex+1], (mCount - materialIndex) * sizeof(*mList));

	// Delete the triangles that used it

	deleteMarkedTris(1);
}

//---------------------------------------------------------------------------
// EditTriMesh::deletePart
//
// Deletes one part from the part list.  Part indices in the triangles are
// fixed up and any triangles from that part are deleted

void	EditTriMesh::deletePart(int partIndex) {

	// Check index.  Warn in debug build, don't crash release

	if ((partIndex < 0) || (partIndex >= partCount())) {
		assert(false);
		return;
	}

	// Scan triangle list and fixup vertex indices

	for (int i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);

		// Do we need to delete it?

		if (t->part == partIndex) {
			t->mark = 1;
		} else {
			t->mark = 0;
			if (t->part > partIndex) {
				--t->part;
			}
		}
	}

	// Delete it

	--pCount;
	memmove(&pList[partIndex], &pList[partIndex+1], (pCount - partIndex) * sizeof(*pList));

	// Delete the triangles that used it

	deleteMarkedTris(1);
}

//---------------------------------------------------------------------------
// EditTriMesh::deleteUnusedMaterials
//
// Scan list of materials and delete any that are not used by any triangles
//
// This method may seem a little more complicated, but it operates
// in linear time with respect to the number of triangles.
// Other methods will run in quadratic time or worse.

void	EditTriMesh::deleteUnusedMaterials() {

	int i;

	// Assume all materials will be unused

	markAllMaterials(0);

	// Scan triangle list and mark referenced materials

	for (i = 0 ; i < triCount() ; ++i) {
		material(tri(i).material).mark = 1;
	}

	// OK, figure out how many materials there will be,
	// and where they will go int he new material list,
	// after the unused ones are removed

	int	newMaterialCount = 0;
	for (i = 0 ; i < materialCount() ; ++i) {
		Material *m = &material(i);

		// Was it used?

		if (m->mark == 0) {

			// No - mark it to be whacked

			m->mark = -1;

		} else {

			// Yes - it will occupy the next slot in the
			// new material list

			m->mark = newMaterialCount;
			++newMaterialCount;
		}
	}

	// Check if nothing got deleted, then don't bother with the
	// rest of this

	if (newMaterialCount == materialCount()) {
		return;
	}

	// Fixup indices in the face list

	for (i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);
		t->material = material(t->material).mark;
	}

	// Remove the empty spaces from the material list

	int	destMaterialIndex = 0;
	for (i = 0 ; i < materialCount() ; ++i) {
		const Material *m = &material(i);

		// This one staying?

		if (m->mark != -1) {
			assert(m->mark == destMaterialIndex);
			if (i != destMaterialIndex) {
				material(destMaterialIndex) = *m;
			}
			++destMaterialIndex;
		}
	}
	assert(destMaterialIndex == newMaterialCount);

	// Set the new count.  We don't call the function to
	// do this, since it will scan for triangles that use the
	// whacked entries.  We already took care of that.

	mCount = newMaterialCount;
}

//---------------------------------------------------------------------------
// EditTriMesh::deleteEmptyParts
//
// Scan list of parts and delete any that do not contain any triangles
//
// This method may seem a little more complicated, but it operates
// in linear time with respect to the number of triangles.
// Other methods will run in quadratic time or worse.

void	EditTriMesh::deleteEmptyParts() {

	int i;

	// Assume all parts will be empty

	markAllParts(0);

	// Scan triangle list and mark referenced parts

	for (i = 0 ; i < triCount() ; ++i) {
		part(tri(i).part).mark = 1;
	}

	// OK, figure out how many parts there will be,
	// and where they will go int he new part list,
	// after the unused ones are removed

	int	newPartCount = 0;
	for (i = 0 ; i < partCount() ; ++i) {
		Part *p = &part(i);

		// Was it used?

		if (p->mark == 0) {

			// No - mark it to be whacked

			p->mark = -1;

		} else {

			// Yes - it will occupy the next slot in the
			// new part list

			p->mark = newPartCount;
			++newPartCount;
		}
	}

	// Check if nothing got deleted, then don't bother with the
	// rest of this

	if (newPartCount == partCount()) {
		return;
	}

	// Fixup indices in the face list

	for (i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);
		t->part = part(t->part).mark;
	}

	// Remove the empty spaces from the part list

	int	destPartIndex = 0;
	for (i = 0 ; i < partCount() ; ++i) {
		const Part *p = &part(i);

		// This one staying?

		if (p->mark != -1) {
			assert(p->mark == destPartIndex);
			if (i != destPartIndex) {
				part(destPartIndex) = *p;
			}
			++destPartIndex;
		}
	}
	assert(destPartIndex == newPartCount);

	// Set the new count.  We don't call the function to
	// do this, since it will scan for triangles that use the
	// whacked entries.  We already took care of that.

	pCount = newPartCount;
}

//---------------------------------------------------------------------------
// EditTriMesh::deleteMarkedTris
//
// Scan triangle list, deleting triangles with the given mark

void	EditTriMesh::deleteMarkedTris(int mark) {

	// Scan triangle list, and move triangles forward to
	// suck up the "holes" left by deleted triangles

	int	destTriIndex = 0;
	for (int i = 0 ; i < triCount() ; ++i) {
		const Tri *t = &tri(i);

		// Is it staying?

		if (t->mark != mark) {
			if (destTriIndex != i) {
				tri(destTriIndex) = *t;
			}
			++destTriIndex;
		}
	}

	// Set new triangle count

	setTriCount(destTriIndex);
}

//---------------------------------------------------------------------------
// EditTriMesh::deleteDegenerateTris
//
// Scan triangle list and remove "degenerate" triangles.  See
// isDegenerate() for the defininition of "degenerate" in this case.

void	EditTriMesh::deleteDegenerateTris() {

	// Scan triangle list, marking the bad ones

	for (int i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);

		// Is it bogus?

		if (t->isDegenerate()) {

			// Mark it to be whacked

			t->mark = 1;

		} else {

			// Keep it

			t->mark = 0;
		}
	}

	// Delete the bad triangles that we found

	deleteMarkedTris(1);
}

//---------------------------------------------------------------------------
// EditTriMesh::detachAllFaces
//
// Detach all the faces from one another.  This creates a new vertex list,
// with each vertex only used by one triangle.  Simultaneously, unused
// vertices are removed.

void	EditTriMesh::detachAllFaces() {

	// Check if we don't have any faces, then bail now.
	// This saves us a crash with a spurrious "out of memory"

	if (triCount() < 1) {
		return;
	}

	// Figure out how many triangles we'll have

	int	newVertexCount = triCount() * 3;

	// Allocate a new vertex list

	Vertex *newVertexList = (Vertex *)::malloc(newVertexCount * sizeof(Vertex));

	// Check for out of memory.  You may need more
	// robust error handling...

	if (newVertexList == NULL) {
		ABORT("Out of memory");
	}

	// Scan the triangle list and fill it in

	for (int i = 0 ; i < triCount() ; ++i) {
		Tri *t = &tri(i);

		// Process the three vertices on this face

		for (int j = 0 ; j < 3 ; ++j) {

			// Get source and destination vertex indices

			int	sIndex = t->v[j].index;
			int	dIndex = i*3 + j;
			Vertex	*dPtr = &newVertexList[dIndex];

			// Copy the vertex

			*dPtr = vertex(sIndex);

			// Go ahead and fill in UV and normal now.  It can't hurt

			dPtr->u = t->v[j].u;
			dPtr->v = t->v[j].v;
			dPtr->normal = t->normal;

			// Set new vertex index

			t->v[j].index = dIndex;
		}
	}

	// Free the old vertex list

	::free(vList);

	// Install the new one

	vList = newVertexList;
	vCount = newVertexCount;
	vAlloc = newVertexCount;
}

//---------------------------------------------------------------------------
// EditTriMesh::transformVertices
//
// Transform all the vertices.  We could transform the surface normals,
// but they may not even be valid, anyway.  If you need them, compute them.

void	EditTriMesh::transformVertices(const Matrix4x3 &m) {
	for (int i = 0 ; i < vertexCount() ; ++i) {
		vertex(i).p *= m;
	}
}

//---------------------------------------------------------------------------
// EditTriMesh::extractParts
//
// Extract each part into a seperate mesh.  Each resulting mesh will
// have exactly one part

void	EditTriMesh::extractParts(EditTriMesh *meshes) {

	// !SPEED! This function will run in O(partCount * triCount).
	// We could optimize it somewhat by having the triangles sorted by
	// part.  However, any real optimization would be considerably
	// more complicated.  Let's just keep it simple.

	// Scan through each part

	for (int partIndex = 0 ; partIndex < partCount() ; ++partIndex) {

		// Get shortcut to destination mesh

		EditTriMesh *dMesh = &meshes[partIndex];

		// Mark all vertices and materials, assuming they will
		// not be used by this part

		markAllVertices(-1);
		markAllMaterials(-1);

		// Setup the destination part mesh with a single part

		dMesh->empty();
		dMesh->setPartCount(1);
		dMesh->part(0) = part(partIndex);

		// Convert face list, simultaneously building material and
		// vertex list

		for (int faceIndex = 0 ; faceIndex < triCount() ; ++faceIndex) {

			// Fetch shortcut, make sure it belongs to this
			// part

			Tri *tPtr = &tri(faceIndex);
			if (tPtr->part != partIndex) {
				continue;
			}

			// Make a copy

			Tri t = *tPtr;

			// Remap material index

			Material *m = &material(t.material);
			if (m->mark < 0) {
				m->mark = dMesh->addMaterial(*m);
			}
			t.material = m->mark;

			// Remap vertices

			for (int j = 0 ; j < 3 ; ++j) {
				Vertex *v = &vertex(t.v[j].index);
				if (v->mark < 0) {
					v->mark = dMesh->addVertex(*v);
				}
				t.v[j].index = v->mark;
			}

			// Add the face

			t.part = 0;
			dMesh->addTri(t);
		}
	}
}

void	EditTriMesh::extractOnePartOneMaterial(int partIndex, int materialIndex, EditTriMesh *result) {

	// Mark all vertices, assuming they will not be used

	markAllVertices(-1);

	// Setup the destination mesh with a single part and material

	result->empty();
	result->setPartCount(1);
	result->part(0) = part(partIndex);
	result->setMaterialCount(1);
	result->material(0) = material(materialIndex);

	// Convert face list, simultaneously building vertex list

	for (int faceIndex = 0 ; faceIndex < triCount() ; ++faceIndex) {

		// Fetch shortcut, make sure it belongs to this
		// part and uses this material

		Tri *tPtr = &tri(faceIndex);
		if (tPtr->part != partIndex) {
			continue;
		}
		if (tPtr->material != materialIndex) {
			continue;
		}

		// Make a copy

		Tri t = *tPtr;

		// Remap vertices

		for (int j = 0 ; j < 3 ; ++j) {
			Vertex *v = &vertex(t.v[j].index);
			if (v->mark < 0) {
				v->mark = result->addVertex(*v);
			}
			t.v[j].index = v->mark;
		}

		// Add the face

		t.part = 0;
		t.material = 0;
		result->addTri(t);
	}
}

/////////////////////////////////////////////////////////////////////////////
//
// EditTriMesh members - Computations
//
/////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------------
// EditTriMesh::computeOneTriNormal
//
// Compute a single triangle normal.

void	EditTriMesh::computeOneTriNormal(int triIndex) {
	computeOneTriNormal(tri(triIndex));
}

void	EditTriMesh::computeOneTriNormal(Tri &t) {

	// Fetch shortcuts to vertices

	const Vector3 &v1 = vertex(t.v[0].index).p;
	const Vector3 &v2 = vertex(t.v[1].index).p;
	const Vector3 &v3 = vertex(t.v[2].index).p;

	// Compute clockwise edge vectors.  We use the edge vector
	// indexing that agrees with Section 12.6.

	Vector3 e1 = v3 - v2;
	Vector3 e2 = v1 - v3;

	// Cross product to compute surface normal

	t.normal = crossProduct(e1, e2);

	// Normalize it

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -