From da686160c33069b77a7b4c31fd97da5fa5b59baa Mon Sep 17 00:00:00 2001
From: Kahrl <kahrl@gmx.net>
Date: Fri, 15 Jan 2016 02:16:21 +0100
Subject: [PATCH] Make all mesh manipulators in mesh.cpp work with any vertex
 type

cloneMesh() has to use a switch in order to create a different
mesh buffer type depending on vertex type. (Credit: the new cloneMesh
was written by RealBadAngel.)

To avoid repetitive code, all other methods use getVertexPitchFromType()
to automatically adapt the indexing to the vertex type at runtime.
---
 src/mesh.cpp | 269 +++++++++++++++++++++++++++------------------------
 1 file changed, 145 insertions(+), 124 deletions(-)

diff --git a/src/mesh.cpp b/src/mesh.cpp
index 329b93dc9..a800ddf1e 100644
--- a/src/mesh.cpp
+++ b/src/mesh.cpp
@@ -206,146 +206,139 @@ void setMeshColorByNormalXYZ(scene::IMesh *mesh,
 		const video::SColor &colorY,
 		const video::SColor &colorZ)
 {
-	if(mesh == NULL)
+	if (mesh == NULL)
 		return;
-	
+
 	u16 mc = mesh->getMeshBufferCount();
-	for(u16 j=0; j<mc; j++)
-	{
+	for (u16 j = 0; j < mc; j++) {
 		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 vc = buf->getVertexCount();
-		for(u16 i=0; i<vc; i++)
-		{
-			f32 x = fabs(vertices[i].Normal.X);
-			f32 y = fabs(vertices[i].Normal.Y);
-			f32 z = fabs(vertices[i].Normal.Z);
-			if(x >= y && x >= z)
-				vertices[i].Color = colorX;
-			else if(y >= z)
-				vertices[i].Color = colorY;
+		const u32 stride = getVertexPitchFromType(buf->getVertexType());
+		u32 vertex_count = buf->getVertexCount();
+		u8 *vertices = (u8 *)buf->getVertices();
+		for (u32 i = 0; i < vertex_count; i++) {
+			video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+			f32 x = fabs(vertex->Normal.X);
+			f32 y = fabs(vertex->Normal.Y);
+			f32 z = fabs(vertex->Normal.Z);
+			if (x >= y && x >= z)
+				vertex->Color = colorX;
+			else if (y >= z)
+				vertex->Color = colorY;
 			else
-				vertices[i].Color = colorZ;
+				vertex->Color = colorZ;
 
 		}
 	}
 }
 
-void rotateMeshXYby (scene::IMesh *mesh, f64 degrees) 
-{	
+void rotateMeshXYby(scene::IMesh *mesh, f64 degrees)
+{
 	u16 mc = mesh->getMeshBufferCount();
-	for(u16 j = 0; j < mc; j++)
-	{
+	for (u16 j = 0; j < mc; j++) {
 		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 vc = buf->getVertexCount();
-		for(u16 i = 0; i < vc; i++)
-		{
-			vertices[i].Pos.rotateXYBy(degrees);
-		}
+		const u32 stride = getVertexPitchFromType(buf->getVertexType());
+		u32 vertex_count = buf->getVertexCount();
+		u8 *vertices = (u8 *)buf->getVertices();
+		for (u32 i = 0; i < vertex_count; i++)
+			((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXYBy(degrees);
 	}
 }
 
-void rotateMeshXZby (scene::IMesh *mesh, f64 degrees) 
-{	
+void rotateMeshXZby(scene::IMesh *mesh, f64 degrees)
+{
 	u16 mc = mesh->getMeshBufferCount();
-	for(u16 j = 0; j < mc; j++)
-	{
+	for (u16 j = 0; j < mc; j++) {
 		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 vc = buf->getVertexCount();
-		for(u16 i = 0; i < vc; i++)
-		{
-			vertices[i].Pos.rotateXZBy(degrees);
-		}
+		const u32 stride = getVertexPitchFromType(buf->getVertexType());
+		u32 vertex_count = buf->getVertexCount();
+		u8 *vertices = (u8 *)buf->getVertices();
+		for (u32 i = 0; i < vertex_count; i++)
+			((video::S3DVertex *)(vertices + i * stride))->Pos.rotateXZBy(degrees);
 	}
 }
 
-void rotateMeshYZby (scene::IMesh *mesh, f64 degrees) 
-{	
+void rotateMeshYZby(scene::IMesh *mesh, f64 degrees)
+{
 	u16 mc = mesh->getMeshBufferCount();
-	for(u16 j = 0; j < mc; j++)
-	{
+	for (u16 j = 0; j < mc; j++) {
 		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 vc = buf->getVertexCount();
-		for(u16 i = 0; i < vc; i++)
-		{
-			vertices[i].Pos.rotateYZBy(degrees);
-		}
+		const u32 stride = getVertexPitchFromType(buf->getVertexType());
+		u32 vertex_count = buf->getVertexCount();
+		u8 *vertices = (u8 *)buf->getVertices();
+		for (u32 i = 0; i < vertex_count; i++)
+			((video::S3DVertex *)(vertices + i * stride))->Pos.rotateYZBy(degrees);
 	}
 }
 
 void rotateMeshBy6dFacedir(scene::IMesh *mesh, int facedir)
-{		
-	int axisdir = facedir>>2;
+{
+	int axisdir = facedir >> 2;
 	facedir &= 0x03;
 
 	u16 mc = mesh->getMeshBufferCount();
-	for(u16 j = 0; j < mc; j++)
-	{
+	for (u16 j = 0; j < mc; j++) {
 		scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 vc = buf->getVertexCount();
-		for(u16 i=0; i<vc; i++)
-		{
-			switch (axisdir)
-			{
-			case 0:
-				if(facedir == 1)
-					vertices[i].Pos.rotateXZBy(-90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateXZBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateXZBy(90);
-				break;
-			case 1: // z+
-				vertices[i].Pos.rotateYZBy(90);
-				if(facedir == 1)
-					vertices[i].Pos.rotateXYBy(90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateXYBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateXYBy(-90);
-				break;
-			case 2: //z-
-				vertices[i].Pos.rotateYZBy(-90);
-				if(facedir == 1)
-					vertices[i].Pos.rotateXYBy(-90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateXYBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateXYBy(90);
-				break;
-			case 3:  //x+
-				vertices[i].Pos.rotateXYBy(-90);
-				if(facedir == 1)
-					vertices[i].Pos.rotateYZBy(90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateYZBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateYZBy(-90);
-				break;
-			case 4:  //x-
-				vertices[i].Pos.rotateXYBy(90);
-				if(facedir == 1)
-					vertices[i].Pos.rotateYZBy(-90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateYZBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateYZBy(90);
-				break;
-			case 5:
-				vertices[i].Pos.rotateXYBy(-180);
-				if(facedir == 1)
-					vertices[i].Pos.rotateXZBy(90);
-				else if(facedir == 2)
-					vertices[i].Pos.rotateXZBy(180);
-				else if(facedir == 3)
-					vertices[i].Pos.rotateXZBy(-90);
-				break;
-			default:
-				break;
+		const u32 stride = getVertexPitchFromType(buf->getVertexType());
+		u32 vertex_count = buf->getVertexCount();
+		u8 *vertices = (u8 *)buf->getVertices();
+		for (u32 i = 0; i < vertex_count; i++) {
+			video::S3DVertex *vertex = (video::S3DVertex *)(vertices + i * stride);
+			switch (axisdir) {
+				case 0:
+					if (facedir == 1)
+						vertex->Pos.rotateXZBy(-90);
+					else if (facedir == 2)
+						vertex->Pos.rotateXZBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateXZBy(90);
+					break;
+				case 1: // z+
+					vertex->Pos.rotateYZBy(90);
+					if (facedir == 1)
+						vertex->Pos.rotateXYBy(90);
+					else if (facedir == 2)
+						vertex->Pos.rotateXYBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateXYBy(-90);
+					break;
+				case 2: //z-
+					vertex->Pos.rotateYZBy(-90);
+					if (facedir == 1)
+						vertex->Pos.rotateXYBy(-90);
+					else if (facedir == 2)
+						vertex->Pos.rotateXYBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateXYBy(90);
+					break;
+				case 3:  //x+
+					vertex->Pos.rotateXYBy(-90);
+					if (facedir == 1)
+						vertex->Pos.rotateYZBy(90);
+					else if (facedir == 2)
+						vertex->Pos.rotateYZBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateYZBy(-90);
+					break;
+				case 4:  //x-
+					vertex->Pos.rotateXYBy(90);
+					if (facedir == 1)
+						vertex->Pos.rotateYZBy(-90);
+					else if (facedir == 2)
+						vertex->Pos.rotateYZBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateYZBy(90);
+					break;
+				case 5:
+					vertex->Pos.rotateXYBy(-180);
+					if (facedir == 1)
+						vertex->Pos.rotateXZBy(90);
+					else if (facedir == 2)
+						vertex->Pos.rotateXZBy(180);
+					else if (facedir == 3)
+						vertex->Pos.rotateXZBy(-90);
+					break;
+				default:
+					break;
 			}
 		}
 	}
@@ -355,11 +348,10 @@ void recalculateBoundingBox(scene::IMesh *src_mesh)
 {
 	core::aabbox3d<f32> bbox;
 	bbox.reset(0,0,0);
-	for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
-	{
+	for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
 		scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
 		buf->recalculateBoundingBox();
-		if(j == 0)
+		if (j == 0)
 			bbox = buf->getBoundingBox();
 		else
 			bbox.addInternalBox(buf->getBoundingBox());
@@ -370,18 +362,47 @@ void recalculateBoundingBox(scene::IMesh *src_mesh)
 scene::IMesh* cloneMesh(scene::IMesh *src_mesh)
 {
 	scene::SMesh* dst_mesh = new scene::SMesh();
-	for(u16 j = 0; j < src_mesh->getMeshBufferCount(); j++)
-	{
+	for (u16 j = 0; j < src_mesh->getMeshBufferCount(); j++) {
 		scene::IMeshBuffer *buf = src_mesh->getMeshBuffer(j);
-		video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
-		u16 *indices = (u16*)buf->getIndices();
-		scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
-		temp_buf->append(vertices, buf->getVertexCount(),
-			indices, buf->getIndexCount());
-		dst_mesh->addMeshBuffer(temp_buf);
-		temp_buf->drop();
+		switch (buf->getVertexType()) {
+			case video::EVT_STANDARD: {
+				video::S3DVertex *v =
+					(video::S3DVertex *) buf->getVertices();
+				u16 *indices = (u16*)buf->getIndices();
+				scene::SMeshBuffer *temp_buf = new scene::SMeshBuffer();
+				temp_buf->append(v, buf->getVertexCount(),
+					indices, buf->getIndexCount());
+				dst_mesh->addMeshBuffer(temp_buf);
+				temp_buf->drop();
+				break;
+			}
+			case video::EVT_2TCOORDS: {
+				video::S3DVertex2TCoords *v =
+					(video::S3DVertex2TCoords *) buf->getVertices();
+				u16 *indices = (u16*)buf->getIndices();
+				scene::SMeshBufferTangents *temp_buf =
+					new scene::SMeshBufferTangents();
+				temp_buf->append(v, buf->getVertexCount(),
+					indices, buf->getIndexCount());
+				dst_mesh->addMeshBuffer(temp_buf);
+				temp_buf->drop();
+				break;
+			}
+			case video::EVT_TANGENTS: {
+				video::S3DVertexTangents *v =
+					(video::S3DVertexTangents *) buf->getVertices();
+				u16 *indices = (u16*)buf->getIndices();
+				scene::SMeshBufferTangents *temp_buf =
+					new scene::SMeshBufferTangents();
+				temp_buf->append(v, buf->getVertexCount(),
+					indices, buf->getIndexCount());
+				dst_mesh->addMeshBuffer(temp_buf);
+				temp_buf->drop();
+				break;
+			}
+		}
 	}
-	return dst_mesh;					
+	return dst_mesh;
 }
 
 scene::IMesh* convertNodeboxNodeToMesh(ContentFeatures *f)
-- 
GitLab