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

📄 edittrimesh.cpp

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

	t.normal.normalize();
}

//---------------------------------------------------------------------------
// EditTriMesh::computeTriNormals
//
// Compute all the triangle normals

void	EditTriMesh::computeTriNormals() {
	for (int i = 0 ; i < triCount() ; ++i) {
		computeOneTriNormal(tri(i));
	}
}

//---------------------------------------------------------------------------
// EditTriMesh::computeTriNormals
//
// Compute vertex level surface normals.  This automatically computes the
// triangle level surface normals

void	EditTriMesh::computeVertexNormals() {

	int	i;

	// First, make sure triangle level surface normals are up-to-date

	computeTriNormals();

	// Zero out vertex normals

	for (i = 0 ; i < vertexCount() ; ++i) {
		vertex(i).normal.zero();
	}

	// Sum in the triangle normals into the vertex normals
	// that are used by the triangle

	for (i = 0 ; i < triCount() ; ++i) {
		const Tri *t = &tri(i);
		for (int j = 0 ; j < 3 ; ++j) {
			vertex(t->v[j].index).normal += t->normal;
		}
	}

	// Now "average" the vertex surface normals, by normalizing them

	for (i = 0 ; i < vertexCount() ; ++i) {
		vertex(i).normal.normalize();
	}
}

//---------------------------------------------------------------------------
// EditTriMesh::computeBounds
//
// Compute the bounding box of the mesh

AABB3	EditTriMesh::computeBounds() const {

	// Generate the bounding box of the vertices

	AABB3	box;
	box.empty();
	for (int i = 0 ; i < vertexCount() ; ++i) {
		box.add(vertex(i).p);
	}

	// Return it

	return box;
}

/////////////////////////////////////////////////////////////////////////////
//
// EditTriMesh members - Optimization
//
/////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------------
// EditTriMesh::optimizeVertexOrder
//
// Re-order the vertex list, in the order that they are used by the faces.
// This can improve cache performace and vertex caching by increasing the
// locality of reference.
//
// If removeUnusedVertices is true, then any unused vertices are discarded.
// Otherwise, they are retained at the end of the vertex list.  Normally
// you will want to discard them, which is why we default the paramater to
// true.

void	EditTriMesh::optimizeVertexOrder(bool removeUnusedVertices) {

	int	i;

	// Mark all vertices with a very high mark, which assumes
	// that they will not be used

	for (i = 0 ; i < vertexCount() ; ++i) {
		vertex(i).mark = vertexCount();
	}

	// Scan the face list, and figure out where the vertices
	// will end up in the new, ordered list.  At the same time,
	// we remap the indices in the triangles according to this
	// new ordering.

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

		// Process each of the three vertices on this triangle

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

			// Get shortcut to the vertex used

			Vertex *v = &vertex(t->v[j].index);

			// Has it been used already?

			if (v->mark == vertexCount()) {

				// We're the first triangle to use
				// this one.  Assign the vertex to
				// the next slot in the new vertex
				// list

				v->mark = usedVertexCount;
				++usedVertexCount;
			}

			// Remap the vertex index

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

	// Re-sort the vertex list.  This puts the used vertices
	// in order where they go, and moves all the unused vertices
	// to the end (in no particular order, since qsort is not
	// a stable sort)

	qsort(vList, vertexCount(), sizeof(Vertex), vertexCompareByMark);

	// Did they want to discard the unused guys?

	if (removeUnusedVertices) {

		// Yep - chop off the unused vertices by slamming
		// the vertex count.  We don't call the function to
		// set the vertex count here, since it will scan
		// the triangle list for any triangle that use those
		// vertices.  But we already know that all of the
		// vertices we are deleting are unused

		vCount = usedVertexCount;
	}
}

//---------------------------------------------------------------------------
// EditTriMesh::sortTrisByMaterial
//
// Sort triangles by material.  This is VERY important for effecient
// rendering

void	EditTriMesh::sortTrisByMaterial() {

	// Put the current index into the "mark" field so we can
	// have a stable sort

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

	// Use qsort

	qsort(tList, triCount(), sizeof(Tri), triCompareByMaterial);
}

//---------------------------------------------------------------------------
// EditTriMesh::weldVertices
//
// Weld coincident vertices.  For the moment, this disregards UVs and welds
// all vertices that are within geometric tolerance

void	EditTriMesh::weldVertices(const OptimizationParameters &opt) {

	// !FIXME!

}

//---------------------------------------------------------------------------
// EditTriMesh::copyUvsIntoVertices
//
// Ensure that the vertex UVs are correct, possibly duplicating
// vertices if necessary

void	EditTriMesh::copyUvsIntoVertices() {

	// Mark all vertices indicating thet their UV's are invalid

	markAllVertices(0);

	// Scan the faces, and shove in the UV's into the vertices

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

			// Locate vertex

			int	vIndex = triPtr->v[i].index;
			Vertex *vPtr = &vertex(vIndex);

			// Have we filled in the UVs for this vertex yet?

			if (vPtr->mark == 0) {

				// Nope.  Shove them in

				vPtr->u = triPtr->v[i].u;
				vPtr->v = triPtr->v[i].v;

				// Mark UV's as valid, and keep going

				vPtr->mark = 1;
				continue;
			}

			// UV's have already been filled in by another face.
			// Did that face have the same UV's as me?

			if (
				(vPtr->u == triPtr->v[i].u) &&
				(vPtr->v == triPtr->v[i].v)
			) {

				// Yep - no need to change anything

				continue;
			}

			// OK, we can't use this vertex - somebody else already has
			// it "claimed" with different UV's.  First, we'll search
			// for another vertex with the same position.  Yikes - 
			// this requires a linear search through the vertex list.
			// Luckily, this should not happen the majority of the time.

			bool	foundOne = false;
			for (int newIndex = 0 ; newIndex < vertexCount() ; ++newIndex) {
				Vertex *newPtr = &vertex(newIndex);

				// Is the position and normal correct?

				if (
					(newPtr->p != vPtr->p) ||
					(newPtr->normal != vPtr->normal)
				) {
					continue;
				}

				// OK, this vertex is geometrically correct.
				// Has anybody filled in the UV's yet?

				if (newPtr->mark == 0) {

					// We can claim this one.

					newPtr->mark = 1;
					newPtr->u = triPtr->v[i].u;
					newPtr->v = triPtr->v[i].v;

					// Remap vertex index

					triPtr->v[i].index = newIndex;

					// No need to keep looking

					foundOne = true;
					break;
				}

				// Already claimed by somebody else, so we can't change
				// them.  but are they correct, already anyway?

				if (
					(newPtr->u == triPtr->v[i].u) &&
					(newPtr->v == triPtr->v[i].v)
				) {

					// Yep - no need to change anything.  Just remap the
					// vertex index 

					triPtr->v[i].index = newIndex;

					// No need to keep looking

					foundOne = true;
					break;
				}

				// No good - keep looking
			}

			// Did we find a vertex?

			if (!foundOne) {

				// Nope, we'll have to create a new one

				Vertex newVertex = *vPtr;
				newVertex.mark = 1;
				newVertex.u = triPtr->v[i].u;
				newVertex.v = triPtr->v[i].v;
				triPtr->v[i].index = addVertex(newVertex);
			}
		}
	}
}

// Do all of the optimizations and prepare the model
// for fast rendering under *most* rendering systems,
// with proper lighting.

void	EditTriMesh::optimizeForRendering() {
	computeVertexNormals();
}

/////////////////////////////////////////////////////////////////////////////
//
// EditTriMesh members - Import/Export S3D format
//
// For more on the S3D file format, and free tools for using the
// S3D format with popular rendering packages, visit
// gamemath.com
//
/////////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------------
// EditTriMesh::importS3d
//
// Load up an S3D file.  Returns true on success.  If failure, returns
// false and puts an error message into returnErrMsg

bool	EditTriMesh::importS3d(const char *filename, char *returnErrMsg) {
	int	i;

	// Try to open up the file

	FILE *f = fopen(filename, "rt");
	if (f == NULL) {
		strcpy(returnErrMsg, "Can't open file");
failed:
		empty();
		if (f != NULL) {
			fclose(f);
		}
		return false;
	}

	// Read and check version

	if (!skipLine(f)) {
corrupt:
		strcpy(returnErrMsg, "File is corrupt");
		goto failed;
	}
	int	version;
	if (fscanf(f, "%d\n", &version) != 1) {
		goto corrupt;
	}
	if (version != 103) {
		sprintf(returnErrMsg, "File is version %d - only version 103 supported", version);
		goto failed;
	}

	// Read header

	if (!skipLine(f)) {
		goto corrupt;
	}
	int	numTextures, numTris, numVerts, numParts, numFrames, numLights, numCameras;
	if (fscanf(f, "%d , %d , %d , %d , %d , %d , %d\n", &numTextures, &numTris, &numVerts, &numParts, &numFrames, &numLights, &numCameras) != 7) {
		goto corrupt;
	}

	// Allocate lists

	setMaterialCount(numTextures);
	setTriCount(numTris);
	setVertexCount(numVerts);
	setPartCount(numParts);

	// Read part list.  the only number we care about
	// is the triangle count, which we'll temporarily
	// stach into the mark field

	if (!skipLine(f)) {
		goto corrupt;
	}
	int	firstVert = 0, firstTri = 0;
	for (i = 0 ; i < numParts ; ++i) {
		Part *p = &part(i);
		int	partFirstVert, partNumVerts, partFirstTri, partNumTris;
		if (fscanf(f, "%d , %d , %d , %d , \"%[^\"]\"\n", &partFirstVert, &partNumVerts, &partFirstTri, &partNumTris, p->name) != 5) {
			sprintf(returnErrMsg, "Corrupt at part %d", i);
			goto failed;
		}
		if (firstVert != partFirstVert || firstTri != partFirstTri) {
			sprintf(returnErrMsg, "Part vertex/tri mismatch detected at part %d", i);
			goto failed;
		}
		p->mark = partNumTris;
		firstVert += partNumVerts;
		firstTri += partNumTris;
	}
	if (firstVert != numVerts || firstTri != numTris) {
		strcpy(returnErrMsg, "Part vertex/tri mismatch detected at end of part list");
		goto failed;
	}

	// Read textures.

	if (!skipLine(f)) {
		goto corrupt;
	}
	for (i = 0 ; i < numTextures ; ++i) {
		Material	*m = &material(i);

		// Fetch line of text

		if (fgets(m->diffuseTextureName, sizeof(m->diffuseTextureName), f) != m->diffuseTextureName) {
			sprintf(returnErrMsg, "Corrupt reading texture %d", i);
			goto failed;
		}

		// Styrip off newline, which fgets leaves.
		// Wouldn't it have been nice if the stdio
		// functions would just have a function to read a line
		// WITHOUT the newline character.  What a pain...

		char *nl = strchr(m->diffuseTextureName, '\n');
		if (nl != NULL) {
			*nl = '\0';
		}
	}

	// Read triangles a part at a time

	if (!skipLine(f)) {
		goto corrupt;
	}
	int	whiteTextureIndex = -1;
	int	destTriIndex = 0;
	for (int partIndex = 0 ; partIndex < numParts ; ++partIndex) {

		// Read all triangles in this part

		for (int i = 0 ; i < part(partIndex).mark ; ++i) {

			// get shortcut to destination triangle

			Tri *t = &tri(destTriIndex);

			// Slam part number

			t->part = partIndex;

			// Parse values from file

			if (fscanf(f, "%d , %d , %f , %f , %d , %f , %f , %d , %f , %f\n",
				&t->material,
				&t->v[0].index, &t->v[0].u, &t->v[0].v,
				&t->v[1].index, &t->v[1].u, &t->v[1].v,
				&t->v[2].index, &t->v[2].u, &t->v[2].v
			) != 10) {
				sprintf(returnErrMsg, "Corrupt reading triangle %d (%d of part %d)", destTriIndex, i, partIndex);
				goto failed;
			}

			// Check for untextured triangle

			if (t->material < 0) {
				if (whiteTextureIndex < 0) {
					Material whiteMaterial;
					strcpy(whiteMaterial.diffuseTextureName, "White");
					whiteTextureIndex = addMaterial(whiteMaterial);
				}
				t->material = whiteTextureIndex;
			}

			// Scale UV's to 0...1 range

			t->v[0].u /= 256.0f;
			t->v[0].v /= 256.0f;
			t->v[1].u /= 256.0f;
			t->v[1].v /= 256.0f;
			t->v[2].u /= 256.0f;
			t->v[2].v /= 256.0f;

			// Next triangle, please

			++destTriIndex;
		}
	}
	assert(destTriIndex == triCount());

	// Read vertices

	if (!skipLine(f)) {
		goto corrupt;
	}
	for (i = 0 ; i < numVerts ; ++i) {
		Vertex *v = &vertex(i);
		if (fscanf(f, "%f , %f , %f\n", &v->p.x, &v->p.y, &v->p.z) != 3) {
			sprintf(returnErrMsg, "Corrupt reading vertex %d", i);
			goto failed;
		}
	}

	// OK, we don't need anything from the rest of the file.  Close file.

	fclose(f);
	f = NULL;

	// Check for structural errors in the mesh

	if (!validityCheck(returnErrMsg)) {
		goto failed;
	}

	// OK!

	return true;
}

void	EditTriMesh::exportS3d(const char *filename) {
}

/////////////////////////////////////////////////////////////////////////////
//
// EditTriMesh members - Debugging
//
/////////////////////////////////////////////////////////////////////////////

void	EditTriMesh::validityCheck() {
	char	errMsg[256];
	if (!validityCheck(errMsg)) {
		ABORT("EditTriMesh failed validity check:\n%s", errMsg);
	}
}

bool	EditTriMesh::validityCheck(char *returnErrMsg) {
	return true;
}

⌨️ 快捷键说明

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