Просмотр исходного кода

Merge pull request #57 from dariomanesku/master

Small update on 14-shadowvolumes.
Branimir Karadžić 12 лет назад
Родитель
Сommit
86096bd3cc
2 измененных файлов с 129 добавлено и 71 удалено
  1. 128 64
      examples/14-shadowvolumes/shadowvolumes.cpp
  2. 1 7
      src/vertexdecl.cpp

+ 128 - 64
examples/14-shadowvolumes/shadowvolumes.cpp

@@ -12,6 +12,7 @@ using namespace std::tr1;
 #include <bx/timer.h>
 #include <bx/timer.h>
 #include <bx/readerwriter.h>
 #include <bx/readerwriter.h>
 #include <bx/allocator.h>
 #include <bx/allocator.h>
+#include <bx/hash.h>
 #include <bx/float4_t.h>
 #include <bx/float4_t.h>
 #include "entry/entry.h"
 #include "entry/entry.h"
 #include "fpumath.h"
 #include "fpumath.h"
@@ -700,7 +701,7 @@ struct Edge
 {
 {
 	bool m_faceReverseOrder[2];
 	bool m_faceReverseOrder[2];
 	uint8_t m_faceIndex;
 	uint8_t m_faceIndex;
-	float m_v0[3], m_v1[3];
+	uint16_t m_i0, m_i1;
 };
 };
 
 
 struct Plane
 struct Plane
@@ -816,6 +817,67 @@ struct HalfEdges
 	HalfEdge* m_endPtr;
 	HalfEdge* m_endPtr;
 };
 };
 
 
+struct WeldedVertex
+{
+	uint16_t m_v;
+	bool m_welded;
+};
+
+inline float sqLength(const float _a[3], const float _b[3])
+{
+	const float xx = _a[0] - _b[0];
+	const float yy = _a[1] - _b[1];
+	const float zz = _a[2] - _b[2];
+	return xx*xx + yy*yy + zz*zz;
+}
+
+uint16_t weldVertices(WeldedVertex* _output, const bgfx::VertexDecl& _decl, const void* _data, uint16_t _num, float _epsilon)
+{
+	const uint32_t hashSize = bx::uint32_nextpow2(_num);
+	const uint32_t hashMask = hashSize-1;
+	const float epsilonSq = _epsilon*_epsilon;
+
+	uint32_t numVertices = 0;
+
+	const uint32_t size = sizeof(uint16_t)*(hashSize + _num);
+	uint16_t* hashTable = (uint16_t*)alloca(size);
+	memset(hashTable, 0xff, size);
+
+	uint16_t* next = hashTable + hashSize;
+
+	for (uint32_t ii = 0; ii < _num; ++ii)
+	{
+		float pos[4];
+		vertexUnpack(pos, bgfx::Attrib::Position, _decl, _data, ii);
+		uint32_t hashValue = bx::hashMurmur2A(pos, 3*sizeof(float) ) & hashMask;
+
+		uint16_t offset = hashTable[hashValue];
+		for (; UINT16_MAX != offset; offset = next[offset])
+		{
+			float test[4];
+			vertexUnpack(test, bgfx::Attrib::Position, _decl, _data, _output[offset].m_v);
+
+			if (sqLength(test, pos) < epsilonSq)
+			{
+				_output[ii].m_v = _output[offset].m_v;
+				_output[ii].m_welded = true;
+				break;
+			}
+		}
+
+		if (UINT16_MAX == offset)
+		{
+			_output[ii].m_v = ii;
+			_output[ii].m_welded = false;
+			next[ii] = hashTable[hashValue];
+			hashTable[hashValue] = ii;
+			numVertices++;
+		}
+	}
+
+	return numVertices;
+}
+
 struct Group
 struct Group
 {
 {
 	Group()
 	Group()
@@ -839,62 +901,56 @@ struct Group
 
 
 	typedef struct { float f[6]; } f6_t;
 	typedef struct { float f[6]; } f6_t;
 
 
-	struct EdgeComparator
+	struct EdgeAndPlane
 	{
 	{
-		bool operator()(const f6_t& _a, const f6_t& _b) const
+		EdgeAndPlane(uint16_t _i0, uint16_t _i1)
+			: m_faceIndex(0)
+			, m_i0(_i0)
+			, m_i1(_i1)
 		{
 		{
-			const uint8_t t0 = 0
-				| ( (_a.f[0] < _b.f[0]) << 5)
-				| ( (_a.f[1] < _b.f[1]) << 4)
-				| ( (_a.f[2] < _b.f[2]) << 3)
-				| ( (_a.f[3] < _b.f[3]) << 2)
-				| ( (_a.f[4] < _b.f[4]) << 1)
-				| ( (_a.f[5] < _b.f[5]) << 0)
-				;
-
-			const uint8_t t1 = 0
-				| ( (_a.f[0] > _b.f[0]) << 5)
-				| ( (_a.f[1] > _b.f[1]) << 4)
-				| ( (_a.f[2] > _b.f[2]) << 3)
-				| ( (_a.f[3] > _b.f[3]) << 2)
-				| ( (_a.f[4] > _b.f[4]) << 1)
-				| ( (_a.f[5] > _b.f[5]) << 0)
-				;
-
-			return t0 > t1;
 		}
 		}
+
+		bool m_faceReverseOrder[2];
+		uint8_t m_faceIndex;
+		uint16_t m_i0, m_i1;
+		Plane m_plane[2];
 	};
 	};
 
 
-	void fillStructures(uint16_t _stride)
+	void fillStructures(const bgfx::VertexDecl& _decl)
 	{
 	{
+		uint16_t stride = _decl.getStride();
 		m_faces.clear();
 		m_faces.clear();
 		m_halfEdges.destroy();
 		m_halfEdges.destroy();
 
 
-		//init halfedges
+		//Init halfedges.
 		m_halfEdges.init(m_indices, m_numIndices);
 		m_halfEdges.init(m_indices, m_numIndices);
 
 
-		//init faces and edges
+		//Init faces and edges.
 		m_faces.reserve(m_numIndices/3); //1 face = 3 indices
 		m_faces.reserve(m_numIndices/3); //1 face = 3 indices
 		m_edges = (Edge*)malloc(m_numIndices * sizeof(Edge)); //1 triangle = 3 indices = 3 edges.
 		m_edges = (Edge*)malloc(m_numIndices * sizeof(Edge)); //1 triangle = 3 indices = 3 edges.
 		m_edgePlanesUnalignedPtr = (Plane*)malloc(m_numIndices * sizeof(Plane) + 15);
 		m_edgePlanesUnalignedPtr = (Plane*)malloc(m_numIndices * sizeof(Plane) + 15);
 		m_edgePlanes = (Plane*)bx::alignPtr(m_edgePlanesUnalignedPtr, 0, 16);
 		m_edgePlanes = (Plane*)bx::alignPtr(m_edgePlanesUnalignedPtr, 0, 16);
 
 
-		struct EdgeAndPlane
+		typedef std::map<std::pair<uint16_t, uint16_t>, EdgeAndPlane> EdgeMap;
+		EdgeMap edgeMap;
+
+		//Get unique indices.
+		WeldedVertex* uniqueVertices = (WeldedVertex*)malloc(m_numVertices*sizeof(WeldedVertex) );
+		::weldVertices(uniqueVertices, _decl, m_vertices, m_numVertices, 0.0001f);
+		uint16_t* uniqueIndices = (uint16_t*)malloc(m_numIndices*sizeof(uint16_t) );
+		for (uint32_t ii = 0; ii < m_numIndices; ++ii)
 		{
 		{
-			EdgeAndPlane(const float* _v0, const float* _v1)
-				: m_faceIndex(0)
+			uint16_t index = m_indices[ii];
+			if (uniqueVertices[index].m_welded)
 			{
 			{
-				memcpy(m_v0, _v0, 3*sizeof(float) );
-				memcpy(m_v1, _v1, 3*sizeof(float) );
+				uniqueIndices[ii] = uniqueVertices[index].m_v;
 			}
 			}
-
-			bool m_faceReverseOrder[2];
-			uint8_t m_faceIndex;
-			float m_v0[3], m_v1[3];
-			Plane m_plane[2];
-		};
-		typedef std::map<f6_t, EdgeAndPlane, EdgeComparator> EdgeMap;
-		EdgeMap edgeMap;
+			else
+			{
+				uniqueIndices[ii] = index;
+			}
+		}
+		free(uniqueVertices);
 
 
 		for (uint32_t ii = 0, size = m_numIndices/3; ii < size; ++ii)
 		for (uint32_t ii = 0, size = m_numIndices/3; ii < size; ++ii)
 		{
 		{
@@ -902,9 +958,9 @@ struct Group
 			const uint16_t i0 = indices[0];
 			const uint16_t i0 = indices[0];
 			const uint16_t i1 = indices[1];
 			const uint16_t i1 = indices[1];
 			const uint16_t i2 = indices[2];
 			const uint16_t i2 = indices[2];
-			const float* v0 = (float*)&m_vertices[i0*_stride];
-			const float* v1 = (float*)&m_vertices[i1*_stride];
-			const float* v2 = (float*)&m_vertices[i2*_stride];
+			const float* v0 = (float*)&m_vertices[i0*stride];
+			const float* v1 = (float*)&m_vertices[i1*stride];
+			const float* v2 = (float*)&m_vertices[i2*stride];
 
 
 			float plane[4];
 			float plane[4];
 			planeNormal(plane, v0, v2, v1);
 			planeNormal(plane, v0, v2, v1);
@@ -916,23 +972,26 @@ struct Group
 			memcpy(face.m_plane, plane, 4*sizeof(float) );
 			memcpy(face.m_plane, plane, 4*sizeof(float) );
 			m_faces.push_back(face);
 			m_faces.push_back(face);
 
 
-			const float* triangleV[3][2] =
+			//Use unique indices for EdgeMap.
+			const uint16_t* uindices = &uniqueIndices[ii*3];
+			const uint16_t ui0 = uindices[0];
+			const uint16_t ui1 = uindices[1];
+			const uint16_t ui2 = uindices[2];
+
+			const uint16_t triangleEdge[3][2] =
 			{
 			{
-				{v0, v1},
-				{v1, v2},
-				{v2, v0},
+				{ui0, ui1},
+				{ui1, ui2},
+				{ui2, ui0},
 			};
 			};
 
 
 			for (uint8_t jj = 0; jj < 3; ++jj)
 			for (uint8_t jj = 0; jj < 3; ++jj)
 			{
 			{
-				const float* v0 = triangleV[jj][0];
-				const float* v1 = triangleV[jj][1];
-				f6_t key;
-				f6_t keyInv;
-				memcpy(&key.f[0], v0, 3*sizeof(float) );
-				memcpy(&key.f[3], v1, 3*sizeof(float) );
-				memcpy(&keyInv.f[0], v1, 3*sizeof(float) );
-				memcpy(&keyInv.f[3], v0, 3*sizeof(float) );
+				const uint16_t ui0 = triangleEdge[jj][0];
+				const uint16_t ui1 = triangleEdge[jj][1];
+
+				std::pair<uint16_t, uint16_t> key    = std::make_pair(ui0, ui1);
+				std::pair<uint16_t, uint16_t> keyInv = std::make_pair(ui1, ui0);
 
 
 				EdgeMap::iterator iter = edgeMap.find(keyInv);
 				EdgeMap::iterator iter = edgeMap.find(keyInv);
 				if (iter != edgeMap.end())
 				if (iter != edgeMap.end())
@@ -943,7 +1002,7 @@ struct Group
 				}
 				}
 				else
 				else
 				{
 				{
-					std::pair<EdgeMap::iterator, bool> result = edgeMap.insert(std::make_pair(key, EdgeAndPlane(v0, v1)) );
+					std::pair<EdgeMap::iterator, bool> result = edgeMap.insert(std::make_pair(key, EdgeAndPlane(ui0, ui1) ) );
 					EdgeAndPlane& ep = result.first->second;
 					EdgeAndPlane& ep = result.first->second;
 					memcpy(ep.m_plane[ep.m_faceIndex].m_plane, plane, 4*sizeof(float) );
 					memcpy(ep.m_plane[ep.m_faceIndex].m_plane, plane, 4*sizeof(float) );
 					ep.m_faceReverseOrder[ep.m_faceIndex] = false;
 					ep.m_faceReverseOrder[ep.m_faceIndex] = false;
@@ -952,6 +1011,8 @@ struct Group
 			}
 			}
 		}
 		}
 
 
+		free(uniqueIndices);
+
 		uint32_t index = 0;
 		uint32_t index = 0;
 		for (EdgeMap::const_iterator iter = edgeMap.begin(), end = edgeMap.end(); iter != end; ++iter)
 		for (EdgeMap::const_iterator iter = edgeMap.begin(), end = edgeMap.end(); iter != end; ++iter)
 		{
 		{
@@ -1127,10 +1188,9 @@ struct Mesh
 
 
 		reader.close();
 		reader.close();
 
 
-		uint16_t stride = m_decl.getStride();
 		for (GroupArray::iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
 		for (GroupArray::iterator it = m_groups.begin(), itEnd = m_groups.end(); it != itEnd; ++it)
 		{
 		{
-			it->fillStructures(stride);
+			it->fillStructures(m_decl);
 		}
 		}
 	}
 	}
 
 
@@ -1584,10 +1644,12 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 				int16_t k = res[jj] + res[jj+2];
 				int16_t k = res[jj] + res[jj+2];
 				if (k != 0)
 				if (k != 0)
 				{
 				{
-					verticesSide[vsideI++] = VertexData(edges[ii+jj].m_v0, 0.0f, float(k));
-					verticesSide[vsideI++] = VertexData(edges[ii+jj].m_v0, 1.0f, float(k));
-					verticesSide[vsideI++] = VertexData(edges[ii+jj].m_v1, 0.0f, float(k));
-					verticesSide[vsideI++] = VertexData(edges[ii+jj].m_v1, 1.0f, float(k));
+					float* v0 = (float*)&vertices[edges[ii+jj].m_i0*_stride];
+					float* v1 = (float*)&vertices[edges[ii+jj].m_i1*_stride];
+					verticesSide[vsideI++] = VertexData(v0, 0.0f, float(k));
+					verticesSide[vsideI++] = VertexData(v0, 1.0f, float(k));
+					verticesSide[vsideI++] = VertexData(v1, 0.0f, float(k));
+					verticesSide[vsideI++] = VertexData(v1, 1.0f, float(k));
 
 
 					k = _textureAsStencil ? 1 : k;
 					k = _textureAsStencil ? 1 : k;
 					uint16_t winding = uint16_t(k > 0);
 					uint16_t winding = uint16_t(k > 0);
@@ -1619,10 +1681,12 @@ void shadowVolumeCreate(ShadowVolume& _shadowVolume
 
 
 			if (k != 0)
 			if (k != 0)
 			{
 			{
-				verticesSide[vsideI++] = VertexData(edge.m_v0, 0.0f, k);
-				verticesSide[vsideI++] = VertexData(edge.m_v0, 1.0f, k);
-				verticesSide[vsideI++] = VertexData(edge.m_v1, 0.0f, k);
-				verticesSide[vsideI++] = VertexData(edge.m_v1, 1.0f, k);
+				float* v0 = (float*)&vertices[edge.m_i0*_stride];
+				float* v1 = (float*)&vertices[edge.m_i1*_stride];
+				verticesSide[vsideI++] = VertexData(v0, 0.0f, k);
+				verticesSide[vsideI++] = VertexData(v0, 1.0f, k);
+				verticesSide[vsideI++] = VertexData(v1, 0.0f, k);
+				verticesSide[vsideI++] = VertexData(v1, 1.0f, k);
 
 
 				k = _textureAsStencil ? 1 : k;
 				k = _textureAsStencil ? 1 : k;
 				uint16_t winding = uint16_t(k > 0);
 				uint16_t winding = uint16_t(k > 0);

+ 1 - 7
src/vertexdecl.cpp

@@ -539,10 +539,6 @@ namespace bgfx
 
 
 	uint16_t weldVertices(uint16_t* _output, const VertexDecl& _decl, const void* _data, uint16_t _num, float _epsilon)
 	uint16_t weldVertices(uint16_t* _output, const VertexDecl& _decl, const void* _data, uint16_t _num, float _epsilon)
 	{
 	{
-#if 1
-		return weldVerticesRef(_output, _decl, _data, _num, _epsilon);
-#else
-		// This "clever" version doesn't work as expected...
 		const uint32_t hashSize = bx::uint32_nextpow2(_num);
 		const uint32_t hashSize = bx::uint32_nextpow2(_num);
 		const uint32_t hashMask = hashSize-1;
 		const uint32_t hashMask = hashSize-1;
 		const float epsilonSq = _epsilon*_epsilon;
 		const float epsilonSq = _epsilon*_epsilon;
@@ -577,14 +573,12 @@ namespace bgfx
 			if (UINT16_MAX == offset)
 			if (UINT16_MAX == offset)
 			{
 			{
 				_output[ii] = ii;
 				_output[ii] = ii;
-				next[numVertices] = hashTable[hashValue];
+				next[ii] = hashTable[hashValue];
 				hashTable[hashValue] = ii;
 				hashTable[hashValue] = ii;
 				numVertices++;
 				numVertices++;
 			}
 			}
 		}
 		}
 
 
 		return numVertices;
 		return numVertices;
-#endif // 0
 	}
 	}
-
 } // namespace bgfx
 } // namespace bgfx