1/*
2Bullet Continuous Collision Detection and Physics Library
3Copyright (c) 2010 Erwin Coumans  http://bulletphysics.org
4
5This software is provided 'as-is', without any express or implied warranty.
6In no event will the authors be held liable for any damages arising from the use of this software.
7Permission is granted to anyone to use this software for any purpose,
8including commercial applications, and to alter it and redistribute it freely,
9subject to the following restrictions:
10
111. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
133. This notice may not be removed or altered from any source distribution.
14*/
15
16#ifndef _BT_TRIANGLE_INFO_MAP_H
17#define _BT_TRIANGLE_INFO_MAP_H
18
19
20#include "LinearMath/btHashMap.h"
21#include "LinearMath/btSerializer.h"
22
23
24///for btTriangleInfo m_flags
25#define TRI_INFO_V0V1_CONVEX 1
26#define TRI_INFO_V1V2_CONVEX 2
27#define TRI_INFO_V2V0_CONVEX 4
28
29#define TRI_INFO_V0V1_SWAP_NORMALB 8
30#define TRI_INFO_V1V2_SWAP_NORMALB 16
31#define TRI_INFO_V2V0_SWAP_NORMALB 32
32
33
34///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
35///it can be generated using
36struct	btTriangleInfo
37{
38	btTriangleInfo()
39	{
40		m_edgeV0V1Angle = SIMD_2_PI;
41		m_edgeV1V2Angle = SIMD_2_PI;
42		m_edgeV2V0Angle = SIMD_2_PI;
43		m_flags=0;
44	}
45
46	int			m_flags;
47
48	btScalar	m_edgeV0V1Angle;
49	btScalar	m_edgeV1V2Angle;
50	btScalar	m_edgeV2V0Angle;
51
52};
53
54typedef btHashMap<btHashInt,btTriangleInfo> btInternalTriangleInfoMap;
55
56
57///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
58struct	btTriangleInfoMap : public btInternalTriangleInfoMap
59{
60	btScalar	m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product
61	btScalar	m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
62	btScalar	m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
63	btScalar	m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
64	btScalar	m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
65	btScalar	m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
66
67
68	btTriangleInfoMap()
69	{
70		m_convexEpsilon = 0.00f;
71		m_planarEpsilon = 0.0001f;
72		m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001);
73		m_edgeDistanceThreshold = btScalar(0.1);
74		m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001);
75		m_maxEdgeAngleThreshold = SIMD_2_PI;
76	}
77	virtual ~btTriangleInfoMap() {}
78
79	virtual	int	calculateSerializeBufferSize() const;
80
81	///fills the dataBuffer and returns the struct name (and 0 on failure)
82	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
83
84	void	deSerialize(struct btTriangleInfoMapData& data);
85
86};
87
88///those fields have to be float and not btScalar for the serialization to work properly
89struct	btTriangleInfoData
90{
91	int			m_flags;
92	float	m_edgeV0V1Angle;
93	float	m_edgeV1V2Angle;
94	float	m_edgeV2V0Angle;
95};
96
97struct	btTriangleInfoMapData
98{
99	int					*m_hashTablePtr;
100	int					*m_nextPtr;
101	btTriangleInfoData	*m_valueArrayPtr;
102	int					*m_keyArrayPtr;
103
104	float	m_convexEpsilon;
105	float	m_planarEpsilon;
106	float	m_equalVertexThreshold;
107	float	m_edgeDistanceThreshold;
108	float	m_zeroAreaThreshold;
109
110	int		m_nextSize;
111	int		m_hashTableSize;
112	int		m_numValues;
113	int		m_numKeys;
114	char	m_padding[4];
115};
116
117SIMD_FORCE_INLINE	int	btTriangleInfoMap::calculateSerializeBufferSize() const
118{
119	return sizeof(btTriangleInfoMapData);
120}
121
122///fills the dataBuffer and returns the struct name (and 0 on failure)
123SIMD_FORCE_INLINE	const char*	btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
124{
125	btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
126	tmapData->m_convexEpsilon = (float)m_convexEpsilon;
127	tmapData->m_planarEpsilon = (float)m_planarEpsilon;
128	tmapData->m_equalVertexThreshold =(float) m_equalVertexThreshold;
129	tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
130	tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
131
132	tmapData->m_hashTableSize = m_hashTable.size();
133
134	tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
135	if (tmapData->m_hashTablePtr)
136	{
137		//serialize an int buffer
138		int sz = sizeof(int);
139		int numElem = tmapData->m_hashTableSize;
140		btChunk* chunk = serializer->allocate(sz,numElem);
141		int* memPtr = (int*)chunk->m_oldPtr;
142		for (int i=0;i<numElem;i++,memPtr++)
143		{
144			*memPtr = m_hashTable[i];
145		}
146		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]);
147
148	}
149
150	tmapData->m_nextSize = m_next.size();
151	tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0;
152	if (tmapData->m_nextPtr)
153	{
154		int sz = sizeof(int);
155		int numElem = tmapData->m_nextSize;
156		btChunk* chunk = serializer->allocate(sz,numElem);
157		int* memPtr = (int*)chunk->m_oldPtr;
158		for (int i=0;i<numElem;i++,memPtr++)
159		{
160			*memPtr = m_next[i];
161		}
162		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]);
163	}
164
165	tmapData->m_numValues = m_valueArray.size();
166	tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0;
167	if (tmapData->m_valueArrayPtr)
168	{
169		int sz = sizeof(btTriangleInfoData);
170		int numElem = tmapData->m_numValues;
171		btChunk* chunk = serializer->allocate(sz,numElem);
172		btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
173		for (int i=0;i<numElem;i++,memPtr++)
174		{
175			memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
176			memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
177			memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
178			memPtr->m_flags = m_valueArray[i].m_flags;
179		}
180		serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
181	}
182
183	tmapData->m_numKeys = m_keyArray.size();
184	tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
185	if (tmapData->m_keyArrayPtr)
186	{
187		int sz = sizeof(int);
188		int numElem = tmapData->m_numValues;
189		btChunk* chunk = serializer->allocate(sz,numElem);
190		int* memPtr = (int*)chunk->m_oldPtr;
191		for (int i=0;i<numElem;i++,memPtr++)
192		{
193			*memPtr = m_keyArray[i].getUid1();
194		}
195		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
196
197	}
198	return "btTriangleInfoMapData";
199}
200
201
202
203///fills the dataBuffer and returns the struct name (and 0 on failure)
204SIMD_FORCE_INLINE	void	btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData )
205{
206
207
208	m_convexEpsilon = tmapData.m_convexEpsilon;
209	m_planarEpsilon = tmapData.m_planarEpsilon;
210	m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
211	m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
212	m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
213	m_hashTable.resize(tmapData.m_hashTableSize);
214	int i =0;
215	for (i=0;i<tmapData.m_hashTableSize;i++)
216	{
217		m_hashTable[i] = tmapData.m_hashTablePtr[i];
218	}
219	m_next.resize(tmapData.m_nextSize);
220	for (i=0;i<tmapData.m_nextSize;i++)
221	{
222		m_next[i] = tmapData.m_nextPtr[i];
223	}
224	m_valueArray.resize(tmapData.m_numValues);
225	for (i=0;i<tmapData.m_numValues;i++)
226	{
227		m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
228		m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
229		m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
230		m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
231	}
232
233	m_keyArray.resize(tmapData.m_numKeys,btHashInt(0));
234	for (i=0;i<tmapData.m_numKeys;i++)
235	{
236		m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
237	}
238}
239
240
241#endif //_BT_TRIANGLE_INFO_MAP_H
242