improve friction quality, add shader-only support, improve debug drawing facilities, fix couple things
This commit is contained in:
		
							
								
								
									
										7453
									
								
								external/glad/glad.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7453
									
								
								external/glad/glad.c
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										13138
									
								
								external/glad/glad.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13138
									
								
								external/glad/glad.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										4
									
								
								external/imgui/imgui_impl_glfw_gl3.cpp
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								external/imgui/imgui_impl_glfw_gl3.cpp
									
									
									
									
										vendored
									
									
								
							| @@ -210,7 +210,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() | |||||||
|     glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); |     glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); | ||||||
|  |  | ||||||
|     const GLchar *vertex_shader = |     const GLchar *vertex_shader = | ||||||
|         "#version 130\n" |         "#version 400\n" | ||||||
|         "uniform mat4 ProjMtx;\n" |         "uniform mat4 ProjMtx;\n" | ||||||
|         "in vec2 Position;\n" |         "in vec2 Position;\n" | ||||||
|         "in vec2 UV;\n" |         "in vec2 UV;\n" | ||||||
| @@ -225,7 +225,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() | |||||||
|         "}\n"; |         "}\n"; | ||||||
|  |  | ||||||
|     const GLchar* fragment_shader = |     const GLchar* fragment_shader = | ||||||
|         "#version 130\n" |         "#version 400\n" | ||||||
|         "uniform sampler2D Texture;\n" |         "uniform sampler2D Texture;\n" | ||||||
|         "in vec2 Frag_UV;\n" |         "in vec2 Frag_UV;\n" | ||||||
|         "in vec4 Frag_Color;\n" |         "in vec4 Frag_Color;\n" | ||||||
|   | |||||||
| @@ -19,31 +19,10 @@ | |||||||
| #ifndef B3_MESH_H | #ifndef B3_MESH_H | ||||||
| #define B3_MESH_H | #define B3_MESH_H | ||||||
|  |  | ||||||
| #include <bounce/common/geometry.h> |  | ||||||
| #include <bounce/collision/trees/static_tree.h> | #include <bounce/collision/trees/static_tree.h> | ||||||
|  |  | ||||||
| // A triangle in indexed form. |  | ||||||
| struct b3Triangle | struct b3Triangle | ||||||
| { | { | ||||||
| 	// Does nothing for performance. |  | ||||||
| 	b3Triangle() { } |  | ||||||
|  |  | ||||||
| 	// Set this triangle from three vertices. |  | ||||||
| 	b3Triangle(u32 _v1, u32 _v2, u32 _v3) |  | ||||||
| 	{ |  | ||||||
| 		v1 = _v1; |  | ||||||
| 		v2 = _v2; |  | ||||||
| 		v3 = _v3; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Set this triangle from three vertices. |  | ||||||
| 	void Set(u32 _v1, u32 _v2, u32 _v3) |  | ||||||
| 	{ |  | ||||||
| 		v1 = _v1; |  | ||||||
| 		v2 = _v2; |  | ||||||
| 		v3 = _v3; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// Test if this triangle contains a given vertex. | 	// Test if this triangle contains a given vertex. | ||||||
| 	bool TestVertex(u32 v) const | 	bool TestVertex(u32 v) const | ||||||
| 	{ | 	{ | ||||||
| @@ -67,33 +46,15 @@ struct b3Mesh | |||||||
| 	b3Triangle* triangles; | 	b3Triangle* triangles; | ||||||
| 	b3StaticTree tree; | 	b3StaticTree tree; | ||||||
|  |  | ||||||
| 	void BuildTree(); |  | ||||||
| 	 |  | ||||||
| 	const b3Vec3& GetVertex(u32 index) const; | 	const b3Vec3& GetVertex(u32 index) const; | ||||||
| 	const b3Triangle& GetTriangle(u32 index) const; | 	const b3Triangle& GetTriangle(u32 index) const; | ||||||
| 	 |  | ||||||
| 	void GetTriangleVertices(b3Vec3 out[3], u32 index) const; |  | ||||||
| 	b3Plane GetTrianglePlane(u32 index) const; |  | ||||||
| 	b3AABB3 GetTriangleAABB(u32 index) const; |  | ||||||
| 	u32 GetSize() const; | 	u32 GetSize() const; | ||||||
|  |  | ||||||
|  | 	b3AABB3 GetTriangleAABB(u32 index) const; | ||||||
|  |  | ||||||
|  | 	void BuildTree(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| inline void b3Mesh::BuildTree() |  | ||||||
| { |  | ||||||
| 	b3AABB3* aabbs = (b3AABB3*)b3Alloc(triangleCount * sizeof(b3AABB3)); |  | ||||||
| 	u32* indices = (u32*)b3Alloc(triangleCount * sizeof(u32)); |  | ||||||
| 	for (u32 i = 0; i < triangleCount; ++i) |  | ||||||
| 	{ |  | ||||||
| 		aabbs[i] = GetTriangleAABB(i); |  | ||||||
| 		indices[i] = i; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	tree.Build(indices, aabbs, triangleCount); |  | ||||||
|  |  | ||||||
| 	b3Free(indices); |  | ||||||
| 	b3Free(aabbs); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline const b3Vec3& b3Mesh::GetVertex(u32 index) const | inline const b3Vec3& b3Mesh::GetVertex(u32 index) const | ||||||
| { | { | ||||||
| 	return vertices[index]; | 	return vertices[index]; | ||||||
| @@ -104,22 +65,14 @@ inline const b3Triangle& b3Mesh::GetTriangle(u32 index) const | |||||||
| 	return triangles[index]; | 	return triangles[index]; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline void b3Mesh::GetTriangleVertices(b3Vec3 out[3], u32 index) const | inline u32 b3Mesh::GetSize() const | ||||||
| { | { | ||||||
| 	const b3Triangle* triangle = triangles + index; | 	u32 size = 0; | ||||||
| 	u32 i1 = triangle->v1; | 	size += sizeof(b3Mesh); | ||||||
| 	u32 i2 = triangle->v2; | 	size += sizeof(b3Vec3) * vertexCount; | ||||||
| 	u32 i3 = triangle->v3; | 	size += sizeof(b3Triangle) * triangleCount; | ||||||
| 	out[0] = vertices[i1]; | 	size += tree.GetSize(); | ||||||
| 	out[1] = vertices[i2]; | 	return size; | ||||||
| 	out[2] = vertices[i3]; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| inline b3Plane b3Mesh::GetTrianglePlane(u32 index) const |  | ||||||
| { |  | ||||||
| 	b3Vec3 vs[3]; |  | ||||||
| 	GetTriangleVertices(vs, index); |  | ||||||
| 	return b3Plane(vs[0], vs[1], vs[2]); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| inline b3AABB3 b3Mesh::GetTriangleAABB(u32 index) const | inline b3AABB3 b3Mesh::GetTriangleAABB(u32 index) const | ||||||
| @@ -133,18 +86,20 @@ inline b3AABB3 b3Mesh::GetTriangleAABB(u32 index) const | |||||||
| 	b3AABB3 aabb; | 	b3AABB3 aabb; | ||||||
| 	aabb.m_lower = b3Min(b3Min(vertices[i1], vertices[i2]), vertices[i3]); | 	aabb.m_lower = b3Min(b3Min(vertices[i1], vertices[i2]), vertices[i3]); | ||||||
| 	aabb.m_upper = b3Max(b3Max(vertices[i1], vertices[i2]), vertices[i3]); | 	aabb.m_upper = b3Max(b3Max(vertices[i1], vertices[i2]), vertices[i3]); | ||||||
| 	 |  | ||||||
| 	return aabb; | 	return aabb; | ||||||
| } | } | ||||||
|  |  | ||||||
| inline u32 b3Mesh::GetSize() const | inline void b3Mesh::BuildTree() | ||||||
| { | { | ||||||
| 	u32 size = 0; | 	b3AABB3* aabbs = (b3AABB3*)b3Alloc(triangleCount * sizeof(b3AABB3)); | ||||||
| 	size += sizeof(b3Mesh); | 	for (u32 i = 0; i < triangleCount; ++i) | ||||||
| 	size += sizeof(b3Vec3) * vertexCount; | 	{ | ||||||
| 	size += sizeof(b3Triangle) * triangleCount; | 		aabbs[i] = GetTriangleAABB(i); | ||||||
| 	size += tree.GetSize(); | 	} | ||||||
| 	return size; |  | ||||||
|  | 	tree.Build(aabbs, triangleCount); | ||||||
|  |  | ||||||
|  | 	b3Free(aabbs); | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -33,9 +33,8 @@ public: | |||||||
| 	b3StaticTree(); | 	b3StaticTree(); | ||||||
| 	~b3StaticTree(); | 	~b3StaticTree(); | ||||||
|  |  | ||||||
| 	// Build this tree from a list of AABBs and the list  | 	// Build this tree from a list of AABBs. | ||||||
| 	// of indices to the AABBs. | 	void Build(const b3AABB3* aabbs, u32 count); | ||||||
| 	void Build(u32* indices, const b3AABB3* aabbs, u32 count); |  | ||||||
|  |  | ||||||
| 	// Get the AABB of a given proxy. | 	// Get the AABB of a given proxy. | ||||||
| 	const b3AABB3& GetAABB(u32 proxyId) const; | 	const b3AABB3& GetAABB(u32 proxyId) const; | ||||||
|   | |||||||
| @@ -62,16 +62,22 @@ public : | |||||||
| 	void AppendFlags(u32 flags); | 	void AppendFlags(u32 flags); | ||||||
| 	 | 	 | ||||||
| 	// Draw a point. | 	// Draw a point. | ||||||
| 	virtual void DrawPoint(const b3Vec3& point, const b3Color& color) = 0; | 	virtual void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color) = 0; | ||||||
|  |  | ||||||
| 	// Draw a line segment. | 	// Draw a line segment. | ||||||
| 	virtual void DrawSegment(const b3Vec3& a, const b3Vec3& b, const b3Color& color) = 0; | 	virtual void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color) = 0; | ||||||
|  |  | ||||||
|  | 	// Draw a triangle with vertices ordered CCW. | ||||||
|  | 	virtual void DrawTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color) = 0; | ||||||
|  |  | ||||||
|  | 	// Draw a solid triangle with vertices ordered CCW. | ||||||
|  | 	virtual void DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color) = 0; | ||||||
|  |  | ||||||
| 	// Draw a polygon with vertices ordered CCW. | 	// Draw a polygon with vertices ordered CCW. | ||||||
| 	virtual void DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color) = 0; | 	virtual void DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color) = 0; | ||||||
| 	 | 	 | ||||||
| 	// Draw a solid polygon with vertices ordered CCW. | 	// Draw a solid polygon with vertices ordered CCW. | ||||||
| 	virtual void DrawSolidPolygon(const b3Vec3* vertices, u32 count, const b3Color& color) = 0; | 	virtual void DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color) = 0; | ||||||
|  |  | ||||||
| 	// Draw a circle with center, normal, and radius. | 	// Draw a circle with center, normal, and radius. | ||||||
| 	virtual void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0; | 	virtual void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color) = 0; | ||||||
|   | |||||||
| @@ -62,9 +62,16 @@ struct b3VelocityConstraintPoint | |||||||
| { | { | ||||||
| 	b3Vec3 rA; | 	b3Vec3 rA; | ||||||
| 	b3Vec3 rB; | 	b3Vec3 rB; | ||||||
|  | 	 | ||||||
| 	b3Vec3 normal; | 	b3Vec3 normal; | ||||||
| 	float32 normalMass; | 	float32 normalMass; | ||||||
| 	float32 normalImpulse; | 	float32 normalImpulse; | ||||||
|  | 	 | ||||||
|  | 	b3Vec3 tangent1; | ||||||
|  | 	b3Vec3 tangent2; | ||||||
|  | 	b3Mat22 tangentMass; | ||||||
|  | 	b3Vec2 tangentImpulse; | ||||||
|  |  | ||||||
| 	float32 velocityBias; | 	float32 velocityBias; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -80,8 +87,6 @@ struct b3VelocityConstraintManifold | |||||||
| 	b3Vec2 tangentImpulse;	 | 	b3Vec2 tangentImpulse;	 | ||||||
| 	float32 motorImpulse; | 	float32 motorImpulse; | ||||||
| 	float32 motorMass; | 	float32 motorMass; | ||||||
| 	//float32 maxTangentImpulse; |  | ||||||
| 	//float32 area; |  | ||||||
| 	 | 	 | ||||||
| 	b3VelocityConstraintPoint* points; | 	b3VelocityConstraintPoint* points; | ||||||
| 	u32 pointCount; | 	u32 pointCount; | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ struct b3ManifoldPoint | |||||||
| 	b3Vec3 localPoint; // local point on the first shape	 | 	b3Vec3 localPoint; // local point on the first shape	 | ||||||
| 	b3Vec3 localPoint2; // local point on the other shape | 	b3Vec3 localPoint2; // local point on the other shape | ||||||
| 	float32 normalImpulse; // normal impulse | 	float32 normalImpulse; // normal impulse | ||||||
|  | 	b3Vec2 tangentImpulse; // tangent impulses  | ||||||
| 	u8 persisting; // indicates that the point is persisting | 	u8 persisting; // indicates that the point is persisting | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -65,8 +66,9 @@ struct b3WorldManifoldPoint | |||||||
| 		const b3Transform& xfA, float32 radiusA, | 		const b3Transform& xfA, float32 radiusA, | ||||||
| 		const b3Transform& xfB, float32 radiusB); | 		const b3Transform& xfB, float32 radiusB); | ||||||
|  |  | ||||||
| 	b3Vec3 normal; |  | ||||||
| 	b3Vec3 point; | 	b3Vec3 point; | ||||||
|  | 	b3Vec3 normal; | ||||||
|  | 	b3Vec2 tangents[2]; | ||||||
| 	float32 separation; | 	float32 separation; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -25,7 +25,8 @@ | |||||||
| struct DrawPoints; | struct DrawPoints; | ||||||
| struct DrawLines; | struct DrawLines; | ||||||
| struct DrawTriangles; | struct DrawTriangles; | ||||||
| struct DrawShapes; | struct DrawWire; | ||||||
|  | struct DrawSolid; | ||||||
|  |  | ||||||
| class Camera | class Camera | ||||||
| { | { | ||||||
| @@ -66,13 +67,17 @@ public: | |||||||
| 	DebugDraw(); | 	DebugDraw(); | ||||||
| 	~DebugDraw(); | 	~DebugDraw(); | ||||||
|  |  | ||||||
| 	void DrawPoint(const b3Vec3& point, const b3Color& color); | 	void DrawPoint(const b3Vec3& p, float32 size, const b3Color& color); | ||||||
|  |  | ||||||
| 	void DrawSegment(const b3Vec3& a, const b3Vec3& b, const b3Color& color); | 	void DrawSegment(const b3Vec3& p1, const b3Vec3& p2, const b3Color& color); | ||||||
|  | 	 | ||||||
|  | 	void DrawTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color); | ||||||
|  |  | ||||||
|  | 	void DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3, const b3Color& color); | ||||||
|  |  | ||||||
| 	void DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color); | 	void DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color); | ||||||
| 	 | 	 | ||||||
| 	void DrawSolidPolygon(const b3Vec3* vertices, u32 count, const b3Color& color); | 	void DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color); | ||||||
|  |  | ||||||
| 	void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color); | 	void DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 radius, const b3Color& color); | ||||||
|  |  | ||||||
| @@ -86,15 +91,30 @@ public: | |||||||
|  |  | ||||||
| 	void DrawTransform(const b3Transform& xf); | 	void DrawTransform(const b3Transform& xf); | ||||||
|  |  | ||||||
|  | 	// | ||||||
| 	void DrawString(const char* string, const b3Color& color, ...); | 	void DrawString(const char* string, const b3Color& color, ...); | ||||||
|  |  | ||||||
| 	void Submit(); | 	void DrawSphere(const b3SphereShape* s, const b3Color& c, const b3Transform& xf); | ||||||
| 	void Submit(const b3World& world); |  | ||||||
|  | 	void DrawCapsule(const b3CapsuleShape* s, const b3Color& c, const b3Transform& xf); | ||||||
|  | 	 | ||||||
|  | 	void DrawHull(const b3HullShape* s, const b3Color& c, const b3Transform& xf); | ||||||
|  | 	 | ||||||
|  | 	void DrawMesh(const b3MeshShape* s, const b3Color& c, const b3Transform& xf); | ||||||
|  |  | ||||||
|  | 	void DrawShape(const b3Shape* s, const b3Color& c, const b3Transform& xf); | ||||||
|  |  | ||||||
|  | 	void Draw(const b3World& world); | ||||||
|  |  | ||||||
|  | 	void Draw(); | ||||||
| private: | private: | ||||||
|  | 	friend struct DrawShapes; | ||||||
|  |  | ||||||
| 	DrawPoints* m_points; | 	DrawPoints* m_points; | ||||||
| 	DrawLines* m_lines; | 	DrawLines* m_lines; | ||||||
| 	DrawTriangles* m_triangles; | 	DrawTriangles* m_triangles; | ||||||
| 	DrawShapes* m_shapes; | 	DrawWire* m_wire; | ||||||
|  | 	DrawSolid* m_solid; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
| @@ -61,10 +61,10 @@ public: | |||||||
| 		 | 		 | ||||||
| 		if (b3Distance(pointA, pointB) > 0.0f) | 		if (b3Distance(pointA, pointB) > 0.0f) | ||||||
| 		{ | 		{ | ||||||
| 			g_debugDraw->DrawPoint(pointA, b3Color(1.0f, 0.0f, 0.0f)); | 			g_debugDraw->DrawPoint(pointA, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawPoint(pointB, b3Color(1.0f, 0.0f, 0.0f)); | 			g_debugDraw->DrawPoint(pointB, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 			 | 			 | ||||||
| 			g_debugDraw->DrawSegment(pointA, pointB, b3Color(1.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawSegment(pointA, pointB, b3Color(1.0f, 1.0f, 1.0f)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		g_debugDraw->DrawTransform(m_xfA); | 		g_debugDraw->DrawTransform(m_xfA); | ||||||
|   | |||||||
| @@ -63,14 +63,14 @@ public: | |||||||
| 		for (u32 i = 0; i < m_clusters.Count(); ++i) | 		for (u32 i = 0; i < m_clusters.Count(); ++i) | ||||||
| 		{ | 		{ | ||||||
| 			g_debugDraw->DrawSegment(b3Vec3(0, 0, 0), m_clusters[i].centroid, b3Color(1, 1, 1)); | 			g_debugDraw->DrawSegment(b3Vec3(0, 0, 0), m_clusters[i].centroid, b3Color(1, 1, 1)); | ||||||
| 			g_debugDraw->DrawPoint(m_clusters[i].centroid, m_colors[i]); | 			g_debugDraw->DrawPoint(m_clusters[i].centroid, 4.0f, m_colors[i]); | ||||||
|  |  | ||||||
| 			for (u32 j = 0; j < m_observs.Count(); ++j) | 			for (u32 j = 0; j < m_observs.Count(); ++j) | ||||||
| 			{ | 			{ | ||||||
| 				b3Observation obs = m_observs[j]; | 				b3Observation obs = m_observs[j]; | ||||||
| 				if (obs.cluster == i) | 				if (obs.cluster == i) | ||||||
| 				{ | 				{ | ||||||
| 					g_debugDraw->DrawPoint(obs.point, m_colors[i]); | 					g_debugDraw->DrawPoint(obs.point, 4.0f, m_colors[i]); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -51,13 +51,13 @@ public: | |||||||
| 			b3Vec3 pw = wmp->point; | 			b3Vec3 pw = wmp->point; | ||||||
| 			b3Vec2 ps = g_camera.ConvertWorldToScreen(pw); | 			b3Vec2 ps = g_camera.ConvertWorldToScreen(pw); | ||||||
| 			 | 			 | ||||||
| 			g_debugDraw->DrawPoint(pw, b3Color(0.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawPoint(pw, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawSegment(pw, pw + wmp->normal, b3Color(1.0f, 1.0f, 1.0f)); | 			g_debugDraw->DrawSegment(pw, pw + wmp->normal, b3Color(1.0f, 1.0f, 1.0f)); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (wm.pointCount > 0) | 		if (wm.pointCount > 0) | ||||||
| 		{ | 		{ | ||||||
| 			g_debugDraw->DrawPoint(wm.center, b3Color(1.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawPoint(wm.center, 4.0f, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.normal, b3Color(1.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.normal, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.tangent1, b3Color(1.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.tangent1, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.tangent2, b3Color(1.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawSegment(wm.center, wm.center + wm.tangent2, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
|   | |||||||
| @@ -57,18 +57,18 @@ public: | |||||||
| 			for (u32 i = 0; i < featurePair.countA; ++i) | 			for (u32 i = 0; i < featurePair.countA; ++i) | ||||||
| 			{ | 			{ | ||||||
| 				u32 index = featurePair.indexA[i]; | 				u32 index = featurePair.indexA[i]; | ||||||
| 				g_debugDraw->DrawPoint(m_xfA * m_proxyA.GetVertex(index), b3Color(1.0f, 1.0f, 0.0f)); | 				g_debugDraw->DrawPoint(m_xfA * m_proxyA.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			for (u32 i = 0; i < featurePair.countB; ++i) | 			for (u32 i = 0; i < featurePair.countB; ++i) | ||||||
| 			{ | 			{ | ||||||
| 				u32 index = featurePair.indexB[i]; | 				u32 index = featurePair.indexB[i]; | ||||||
| 				g_debugDraw->DrawPoint(m_xfB * m_proxyB.GetVertex(index), b3Color(1.0f, 1.0f, 0.0f)); | 				g_debugDraw->DrawPoint(m_xfB * m_proxyB.GetVertex(index), 4.0f, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
| 		g_debugDraw->DrawPoint(out.pointA, b3Color(0.0f, 1.0f, 0.0f)); | 		g_debugDraw->DrawPoint(out.pointA, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 		g_debugDraw->DrawPoint(out.pointB, b3Color(0.0f, 1.0f, 0.0f)); | 		g_debugDraw->DrawPoint(out.pointB, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 		g_debugDraw->DrawSegment(out.pointA, out.pointB, b3Color(1.0f, 1.0f, 1.0f)); | 		g_debugDraw->DrawSegment(out.pointA, out.pointB, b3Color(1.0f, 1.0f, 1.0f)); | ||||||
|  |  | ||||||
| 		g_debugDraw->DrawTransform(m_xfA); | 		g_debugDraw->DrawTransform(m_xfA); | ||||||
|   | |||||||
| @@ -214,7 +214,7 @@ public: | |||||||
| 		{ | 		{ | ||||||
| 			// Replace current hit | 			// Replace current hit | ||||||
| 			g_debugDraw->DrawSegment(p1, hit.point, b3Color(0.0f, 1.0f, 0.0f)); | 			g_debugDraw->DrawSegment(p1, hit.point, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawPoint(hit.point, b3Color(1.0f, 0.0f, 0.0f)); | 			g_debugDraw->DrawPoint(hit.point, 4.0f, b3Color(1.0f, 0.0f, 0.0f)); | ||||||
| 			g_debugDraw->DrawSegment(hit.point, hit.point + hit.normal, b3Color(1.0f, 1.0f, 1.0f)); | 			g_debugDraw->DrawSegment(hit.point, hit.point + hit.normal, b3Color(1.0f, 1.0f, 1.0f)); | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
|   | |||||||
| @@ -36,7 +36,8 @@ struct Settings | |||||||
| 		warmStart = true; | 		warmStart = true; | ||||||
| 		convexCache = true; | 		convexCache = true; | ||||||
| 		drawCenterOfMasses = false; | 		drawCenterOfMasses = false; | ||||||
| 		drawShapes = true; | 		drawVerticesEdges = true; | ||||||
|  | 		drawFaces = true; | ||||||
| 		drawBounds = false; | 		drawBounds = false; | ||||||
| 		drawJoints = true; | 		drawJoints = true; | ||||||
| 		drawContactPoints = true; | 		drawContactPoints = true; | ||||||
| @@ -62,7 +63,8 @@ struct Settings | |||||||
| 	bool convexCache; | 	bool convexCache; | ||||||
| 	bool drawCenterOfMasses; | 	bool drawCenterOfMasses; | ||||||
| 	bool drawBounds; | 	bool drawBounds; | ||||||
| 	bool drawShapes; | 	bool drawVerticesEdges; | ||||||
|  | 	bool drawFaces; | ||||||
| 	bool drawSolidShapes; | 	bool drawSolidShapes; | ||||||
| 	bool drawJoints; | 	bool drawJoints; | ||||||
| 	bool drawContactPoints; | 	bool drawContactPoints; | ||||||
|   | |||||||
| @@ -166,7 +166,7 @@ solution (solution_name) | |||||||
| 		location ( solution_dir .. action ) | 		location ( solution_dir .. action ) | ||||||
| 		includedirs { external_dir, inc_dir } | 		includedirs { external_dir, inc_dir } | ||||||
| 		vpaths { ["Headers"] = "**.h", ["Sources"] = "**.cpp" } | 		vpaths { ["Headers"] = "**.h", ["Sources"] = "**.cpp" } | ||||||
| 		buildoptions { "-std=c++11" } -- require C++11 | 		buildoptions { "-std=c++11" } -- GNU/GCC C++11 | ||||||
|  |  | ||||||
| 		--common | 		--common | ||||||
| 		files  | 		files  | ||||||
| @@ -183,7 +183,7 @@ solution (solution_name) | |||||||
| 		configuration { "not windows", "not macosx" } | 		configuration { "not windows", "not macosx" } | ||||||
| 			links  | 			links  | ||||||
| 			{ 		 | 			{ 		 | ||||||
| 				"GL", "GLU", "rt", "Xrandr", "Xinerama", "Xi", "Xcursor",  | 				"GL", "rt", "Xrandr", "Xinerama", "Xi", "Xcursor",  | ||||||
| 				"m", "dl", "Xrender", "drm", "Xdamage", "X11-xcb", "xcb-glx",  | 				"m", "dl", "Xrender", "drm", "Xdamage", "X11-xcb", "xcb-glx",  | ||||||
| 				"xcb-dri2", "xcb-dri3", "xcb-present", "xcb-sync", "xshmfence",  | 				"xcb-dri2", "xcb-dri3", "xcb-present", "xcb-sync", "xshmfence",  | ||||||
| 				"Xxf86vm", "Xfixes", "Xext", "X11", "pthread", "xcb", "Xau", "Xdmcp"  | 				"Xxf86vm", "Xfixes", "Xext", "X11", "pthread", "xcb", "Xau", "Xdmcp"  | ||||||
|   | |||||||
| @@ -385,44 +385,16 @@ void b3Cloth::Draw(b3Draw* draw) const | |||||||
| 		b3Particle* p2 = m_ps + t->v2; | 		b3Particle* p2 = m_ps + t->v2; | ||||||
| 		b3Particle* p3 = m_ps + t->v3; | 		b3Particle* p3 = m_ps + t->v3; | ||||||
|  |  | ||||||
| 		b3Vec3 vs1[3]; | 		b3Vec3 v1 = p1->p; | ||||||
| 		vs1[0] = p1->p; | 		b3Vec3 v2 = p2->p; | ||||||
| 		vs1[1] = p2->p; | 		b3Vec3 v3 = p3->p; | ||||||
| 		vs1[2] = p3->p; |  | ||||||
|  |  | ||||||
| 		draw->DrawPolygon(vs1, 3, color4); | 		b3Vec3 n1 = b3Cross(v2 - v1, v3 - v1); | ||||||
| 		draw->DrawSolidPolygon(vs1, 3, color3); |  | ||||||
|  |  | ||||||
| 		b3Vec3 vs2[3]; |  | ||||||
| 		vs2[0] = p1->p; |  | ||||||
| 		vs2[1] = p3->p; |  | ||||||
| 		vs2[2] = p2->p; |  | ||||||
|  |  | ||||||
| 		draw->DrawPolygon(vs2, 3, color4); |  | ||||||
| 		draw->DrawSolidPolygon(vs2, 3, color3); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| 	for (u32 i = 0; i < m_c2Count; ++i) |  | ||||||
| 	{ |  | ||||||
| 		b3C2* c = m_c2s + i; |  | ||||||
|  |  | ||||||
| 		b3Particle* p1 = m_ps + c->i1; |  | ||||||
| 		b3Particle* p2 = m_ps + c->i2; |  | ||||||
| 		b3Particle* p3 = m_ps + c->i3; |  | ||||||
| 		b3Particle* p4 = m_ps + c->i4; |  | ||||||
|  |  | ||||||
| 		b3Vec3 c1 = (p1->p + p2->p + p3->p) / 3.0f; |  | ||||||
| 		b3Vec3 n1 = b3Cross(p2->p - p1->p, p3->p - p1->p); |  | ||||||
| 		n1.Normalize(); | 		n1.Normalize(); | ||||||
|  |  | ||||||
| 		draw->DrawSegment(c1, c1 + n1, color1); | 		b3Vec3 n2 = -n1; | ||||||
|  |  | ||||||
| 		b3Vec3 c2 = (p1->p + p4->p + p2->p) / 3.0f; | 		draw->DrawSolidTriangle(n1, v1, v2, v3, color3); | ||||||
| 		b3Vec3 n2 = b3Cross(p2->p - p1->p, p4->p - p1->p); | 		draw->DrawSolidTriangle(n2, v1, v3, v2, color3); | ||||||
| 		n2.Normalize(); |  | ||||||
|  |  | ||||||
| 		draw->DrawSegment(c2, c2 + n2, color1); |  | ||||||
| 	} | 	} | ||||||
| #endif |  | ||||||
| } | } | ||||||
| @@ -60,10 +60,16 @@ struct b3SortPredicate | |||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
| void b3StaticTree::Build(u32* ids, const b3AABB3* set, u32 n) | void b3StaticTree::Build(const b3AABB3* set, u32 n) | ||||||
| { | { | ||||||
| 	B3_ASSERT(n > 0); | 	B3_ASSERT(n > 0); | ||||||
|  |  | ||||||
|  | 	u32* ids = (u32*)b3Alloc(n * sizeof(u32)); | ||||||
|  | 	for (u32 i = 0; i < n; ++i) | ||||||
|  | 	{ | ||||||
|  | 		ids[i] = i; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Leafs = n, Internals = n - 1, Total = 2n - 1, if we assume | 	// Leafs = n, Internals = n - 1, Total = 2n - 1, if we assume | ||||||
| 	// each leaf node contains exactly 1 object. | 	// each leaf node contains exactly 1 object. | ||||||
| 	const u32 kMinObjectsPerLeaf = 1; | 	const u32 kMinObjectsPerLeaf = 1; | ||||||
| @@ -184,6 +190,8 @@ void b3StaticTree::Build(u32* ids, const b3AABB3* set, u32 n) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
|  | 	b3Free(ids); | ||||||
|  |  | ||||||
| 	B3_ASSERT(leafCount == leafCapacity); | 	B3_ASSERT(leafCount == leafCapacity); | ||||||
| 	B3_ASSERT(internalCount == internalCapacity); | 	B3_ASSERT(internalCount == internalCapacity); | ||||||
| 	B3_ASSERT(m_nodeCount == nodeCapacity); | 	B3_ASSERT(m_nodeCount == nodeCapacity); | ||||||
|   | |||||||
| @@ -22,6 +22,9 @@ | |||||||
| #include <bounce/dynamics/body.h> | #include <bounce/dynamics/body.h> | ||||||
| #include <bounce/common/memory/stack_allocator.h> | #include <bounce/common/memory/stack_allocator.h> | ||||||
|  |  | ||||||
|  | // Turn on or off central friction. This is an important optimization for old hardwares.  | ||||||
|  | #define B3_CENTRAL_FRICTION 0 | ||||||
|  |  | ||||||
| // This solver implements PGS for solving velocity constraints and  | // This solver implements PGS for solving velocity constraints and  | ||||||
| // NGS for solving position constraints. | // NGS for solving position constraints. | ||||||
|  |  | ||||||
| @@ -138,6 +141,7 @@ void b3ContactSolver::InitializeConstraints() | |||||||
| 				pcp->localPointB = cp->localPoint2; | 				pcp->localPointB = cp->localPoint2; | ||||||
|  |  | ||||||
| 				vcp->normalImpulse = cp->normalImpulse; | 				vcp->normalImpulse = cp->normalImpulse; | ||||||
|  | 				vcp->tangentImpulse = cp->tangentImpulse; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -225,8 +229,43 @@ void b3ContactSolver::InitializeConstraints() | |||||||
| 						vcp->velocityBias = -vc->restitution * vn; | 						vcp->velocityBias = -vc->restitution * vn; | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | #if B3_CENTRAL_FRICTION == 0 | ||||||
|  | 				// Add friction constraints. | ||||||
|  | 				{ | ||||||
|  | 					vcp->tangent1 = vcm->tangent1; | ||||||
|  | 					vcp->tangent2 = vcm->tangent2; | ||||||
|  |  | ||||||
|  | 					b3Vec3 t1 = vcp->tangent1; | ||||||
|  | 					b3Vec3 t2 = vcp->tangent2; | ||||||
|  |  | ||||||
|  | 					// Compute effective mass. | ||||||
|  | 					// Identities used: | ||||||
|  | 					// I = I^T because I is symmetric. Its inverse is also symmetric. | ||||||
|  | 					// dot(a * u, b * v) = a * b * dot(u, v) | ||||||
|  | 					// dot(t1, t2) = 0 | ||||||
|  | 					b3Vec3 rt1A = b3Cross(rA, t1); | ||||||
|  | 					b3Vec3 rt1B = b3Cross(rB, t1); | ||||||
|  | 					b3Vec3 rt2A = b3Cross(rA, t2); | ||||||
|  | 					b3Vec3 rt2B = b3Cross(rB, t2); | ||||||
|  |  | ||||||
|  | 					float32 kTan11 = mA + mB + b3Dot(iA * rt1A, rt1A) + b3Dot(iB * rt2B, rt2B); | ||||||
|  | 					float32 kTan12 = b3Dot(iA * rt1A, rt2A) + b3Dot(iB * rt1B, rt2B); | ||||||
|  | 					float32 kTan21 = kTan12; | ||||||
|  | 					float32 kTan22 = mA + mB + b3Dot(iA * rt2A, rt2A) + b3Dot(iB * rt2B, rt2B); | ||||||
|  |  | ||||||
|  | 					b3Mat22 K; | ||||||
|  | 					K.x.x = kTan11; | ||||||
|  | 					K.x.y = kTan12; | ||||||
|  | 					K.y.x = kTan21; | ||||||
|  | 					K.y.y = kTan22; | ||||||
|  |  | ||||||
|  | 					vcp->tangentMass = K; | ||||||
|  | 				} | ||||||
|  | #endif | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | #if B3_CENTRAL_FRICTION == 1 | ||||||
| 			if (pointCount > 0) | 			if (pointCount > 0) | ||||||
| 			{ | 			{ | ||||||
| 				b3Vec3 rA = vcm->center - xA; | 				b3Vec3 rA = vcm->center - xA; | ||||||
| @@ -235,7 +274,7 @@ void b3ContactSolver::InitializeConstraints() | |||||||
| 				vcm->rA = rA; | 				vcm->rA = rA; | ||||||
| 				vcm->rB = rB; | 				vcm->rB = rB; | ||||||
|  |  | ||||||
| 				// Add friction constraint. | 				// Add friction constraints. | ||||||
| 				{ | 				{ | ||||||
| 					b3Vec3 t1 = vcm->tangent1; | 					b3Vec3 t1 = vcm->tangent1; | ||||||
| 					b3Vec3 t2 = vcm->tangent2; | 					b3Vec3 t2 = vcm->tangent2; | ||||||
| @@ -270,6 +309,7 @@ void b3ContactSolver::InitializeConstraints() | |||||||
| 					vcm->motorMass = mass > 0.0f ? 1.0f / mass : 0.0f; | 					vcm->motorMass = mass > 0.0f ? 1.0f / mass : 0.0f; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -304,7 +344,10 @@ void b3ContactSolver::WarmStart() | |||||||
| 			{ | 			{ | ||||||
| 				b3VelocityConstraintPoint* vcp = vcm->points + k; | 				b3VelocityConstraintPoint* vcp = vcm->points + k; | ||||||
|  |  | ||||||
| 				b3Vec3 P = vcp->normalImpulse * vcp->normal; | 				b3Vec3 P1 = vcp->normalImpulse * vcp->normal; | ||||||
|  | 				b3Vec3 P2 = vcp->tangentImpulse.x * vcp->tangent1; | ||||||
|  | 				b3Vec3 P3 = vcp->tangentImpulse.y * vcp->tangent2; | ||||||
|  | 				b3Vec3 P = P1 + P2 + P3; | ||||||
|  |  | ||||||
| 				vA -= mA * P; | 				vA -= mA * P; | ||||||
| 				wA -= iA * b3Cross(vcp->rA, P); | 				wA -= iA * b3Cross(vcp->rA, P); | ||||||
| @@ -313,6 +356,7 @@ void b3ContactSolver::WarmStart() | |||||||
| 				wB += iB * b3Cross(vcp->rB, P); | 				wB += iB * b3Cross(vcp->rB, P); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | #if B3_CENTRAL_FRICTION == 1 | ||||||
| 			if (pointCount > 0) | 			if (pointCount > 0) | ||||||
| 			{ | 			{ | ||||||
| 				b3Vec3 P1 = vcm->tangentImpulse.x * vcm->tangent1; | 				b3Vec3 P1 = vcm->tangentImpulse.x * vcm->tangent1; | ||||||
| @@ -325,6 +369,7 @@ void b3ContactSolver::WarmStart() | |||||||
| 				vB += mB * (P1 + P2); | 				vB += mB * (P1 + P2); | ||||||
| 				wB += iB * (b3Cross(vcm->rB, P1 + P2) + P3); | 				wB += iB * (b3Cross(vcm->rB, P1 + P2) + P3); | ||||||
| 			} | 			} | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		m_velocities[indexA].v = vA; | 		m_velocities[indexA].v = vA; | ||||||
| @@ -387,8 +432,43 @@ void b3ContactSolver::SolveVelocityConstraints() | |||||||
|  |  | ||||||
| 					normalImpulse += vcp->normalImpulse; | 					normalImpulse += vcp->normalImpulse; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | #if B3_CENTRAL_FRICTION == 0 | ||||||
|  | 				// Solve tangent constraints. | ||||||
|  | 				{ | ||||||
|  | 					b3Vec3 dv = vB + b3Cross(wB, vcp->rB) - vA - b3Cross(wA, vcp->rA); | ||||||
|  |  | ||||||
|  | 					b3Vec2 Cdot; | ||||||
|  | 					Cdot.x = b3Dot(dv, vcp->tangent1); | ||||||
|  | 					Cdot.y = b3Dot(dv, vcp->tangent2); | ||||||
|  |  | ||||||
|  | 					b3Vec2 impulse = vcp->tangentMass.Solve(-Cdot); | ||||||
|  | 					b3Vec2 oldImpulse = vcp->tangentImpulse; | ||||||
|  | 					vcp->tangentImpulse += impulse; | ||||||
|  |  | ||||||
|  | 					float32 maxImpulse = vc->friction * vcp->normalImpulse; | ||||||
|  | 					if (b3Dot(vcp->tangentImpulse, vcp->tangentImpulse) > maxImpulse * maxImpulse) | ||||||
|  | 					{ | ||||||
|  | 						vcp->tangentImpulse.Normalize(); | ||||||
|  | 						vcp->tangentImpulse *= maxImpulse; | ||||||
|  | 					} | ||||||
|  |  | ||||||
|  | 					impulse = vcp->tangentImpulse - oldImpulse; | ||||||
|  |  | ||||||
|  | 					b3Vec3 P1 = impulse.x * vcp->tangent1; | ||||||
|  | 					b3Vec3 P2 = impulse.y * vcp->tangent2; | ||||||
|  | 					b3Vec3 P = P1 + P2; | ||||||
|  |  | ||||||
|  | 					vA -= mA * P; | ||||||
|  | 					wA -= iA * b3Cross(vcp->rA, P); | ||||||
|  |  | ||||||
|  | 					vB += mB * P; | ||||||
|  | 					wB += iB * b3Cross(vcp->rB, P); | ||||||
|  | 				} | ||||||
|  | #endif | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
|  | #if B3_CENTRAL_FRICTION == 1 | ||||||
| 			if (pointCount > 0) | 			if (pointCount > 0) | ||||||
| 			{ | 			{ | ||||||
| 				// Solve tangent constraints. | 				// Solve tangent constraints. | ||||||
| @@ -438,6 +518,7 @@ void b3ContactSolver::SolveVelocityConstraints() | |||||||
| 					wB += iB * P; | 					wB += iB * P; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | #endif | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		m_velocities[indexA].v = vA; | 		m_velocities[indexA].v = vA; | ||||||
| @@ -471,6 +552,7 @@ void b3ContactSolver::StoreImpulses() | |||||||
| 				b3ManifoldPoint* cp = m->points + k; | 				b3ManifoldPoint* cp = m->points + k; | ||||||
| 				b3VelocityConstraintPoint* vcp = vcm->points + k; | 				b3VelocityConstraintPoint* vcp = vcm->points + k; | ||||||
| 				cp->normalImpulse = vcp->normalImpulse; | 				cp->normalImpulse = vcp->normalImpulse; | ||||||
|  | 				cp->tangentImpulse = vcp->tangentImpulse; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -27,6 +27,7 @@ void b3Manifold::GuessImpulses() | |||||||
| 	{ | 	{ | ||||||
| 		b3ManifoldPoint* p = points + i; | 		b3ManifoldPoint* p = points + i; | ||||||
| 		p->normalImpulse = 0.0f; | 		p->normalImpulse = 0.0f; | ||||||
|  | 		p->tangentImpulse.SetZero(); | ||||||
| 		p->persisting = 0; | 		p->persisting = 0; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -45,6 +46,7 @@ void b3Manifold::FindImpulses(const b3Manifold& oldManifold) | |||||||
| 			if (p2->triangleKey == p1->triangleKey && p2->key == p1->key) | 			if (p2->triangleKey == p1->triangleKey && p2->key == p1->key) | ||||||
| 			{ | 			{ | ||||||
| 				p2->normalImpulse = p1->normalImpulse; | 				p2->normalImpulse = p1->normalImpulse; | ||||||
|  | 				p2->tangentImpulse = p1->tangentImpulse; | ||||||
| 				p2->persisting = 1; | 				p2->persisting = 1; | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @@ -81,6 +83,7 @@ void b3WorldManifold::Initialize(const b3Manifold* manifold, | |||||||
| 	{ | 	{ | ||||||
| 		const b3ManifoldPoint* mp = manifold->points + i; | 		const b3ManifoldPoint* mp = manifold->points + i; | ||||||
| 		b3WorldManifoldPoint* wmp = points + i; | 		b3WorldManifoldPoint* wmp = points + i; | ||||||
|  | 		 | ||||||
| 		wmp->Initialize(mp, xfA, radiusA, xfB, radiusB); | 		wmp->Initialize(mp, xfA, radiusA, xfB, radiusB); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -122,7 +122,7 @@ void b3World::DebugDraw() const | |||||||
| 				 | 				 | ||||||
| 				if (flags & b3Draw::e_contactPointsFlag) | 				if (flags & b3Draw::e_contactPointsFlag) | ||||||
| 				{ | 				{ | ||||||
| 					m_debugDraw->DrawPoint(p, yellow); | 					m_debugDraw->DrawPoint(p, 4.0f, yellow); | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if (flags & b3Draw::e_contactNormalsFlag) | 				if (flags & b3Draw::e_contactNormalsFlag) | ||||||
| @@ -143,18 +143,28 @@ void b3World::DebugDraw() const | |||||||
| 				const b3WorldManifoldPoint* wmp = wm.points + j; | 				const b3WorldManifoldPoint* wmp = wm.points + j; | ||||||
|  |  | ||||||
| 				b3Vec3 n = wmp->normal; | 				b3Vec3 n = wmp->normal; | ||||||
|  | 				b3Vec3 t1 = wm.tangent1; | ||||||
|  | 				b3Vec3 t2 = wm.tangent2; | ||||||
| 				b3Vec3 p = wmp->point; | 				b3Vec3 p = wmp->point; | ||||||
| 				float32 Pn = mp->normalImpulse; | 				float32 Pn = mp->normalImpulse; | ||||||
|  | 				float32 Pt1 = mp->tangentImpulse.x; | ||||||
|  | 				float32 Pt2 = mp->tangentImpulse.y; | ||||||
|  |  | ||||||
| 				if (flags & b3Draw::e_contactPointsFlag) | 				if (flags & b3Draw::e_contactPointsFlag) | ||||||
| 				{ | 				{ | ||||||
| 					m_debugDraw->DrawPoint(p, mp->persisting ? green : red); | 					m_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? green : red); | ||||||
| 				} | 				} | ||||||
| 				 | 				 | ||||||
| 				if (flags & b3Draw::e_contactNormalsFlag) | 				if (flags & b3Draw::e_contactNormalsFlag) | ||||||
| 				{ | 				{ | ||||||
| 					m_debugDraw->DrawSegment(p, p + n, white); | 					m_debugDraw->DrawSegment(p, p + n, white); | ||||||
| 				} | 				} | ||||||
|  | 				 | ||||||
|  | 				if (flags & b3Draw::e_contactTangentsFlag) | ||||||
|  | 				{ | ||||||
|  | 					m_debugDraw->DrawSegment(p, p + t1, yellow); | ||||||
|  | 					m_debugDraw->DrawSegment(p, p + t2, yellow); | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -168,44 +178,34 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const | |||||||
| 	case e_sphereShape: | 	case e_sphereShape: | ||||||
| 	{ | 	{ | ||||||
| 		const b3SphereShape* sphere = (b3SphereShape*)shape; | 		const b3SphereShape* sphere = (b3SphereShape*)shape; | ||||||
| 		b3Vec3 c = xf * sphere->m_center; | 		b3Vec3 p = xf * sphere->m_center; | ||||||
| 		m_debugDraw->DrawPoint(c, wireColor); | 		m_debugDraw->DrawPoint(p, 4.0f, wireColor); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case e_capsuleShape: | 	case e_capsuleShape: | ||||||
| 	{ | 	{ | ||||||
| 		const b3CapsuleShape* capsule = (b3CapsuleShape*)shape; | 		const b3CapsuleShape* capsule = (b3CapsuleShape*)shape; | ||||||
| 		b3Vec3 c1 = xf * capsule->m_centers[0]; | 		b3Vec3 p1 = xf * capsule->m_centers[0]; | ||||||
| 		b3Vec3 c2 = xf * capsule->m_centers[1]; | 		b3Vec3 p2 = xf * capsule->m_centers[1]; | ||||||
| 		 | 		m_debugDraw->DrawPoint(p1, 4.0f, wireColor); | ||||||
| 		m_debugDraw->DrawPoint(c1, wireColor); | 		m_debugDraw->DrawPoint(p2, 4.0f, wireColor); | ||||||
| 		m_debugDraw->DrawPoint(c2, wireColor); | 		m_debugDraw->DrawSegment(p1, p2, wireColor); | ||||||
| 		m_debugDraw->DrawSegment(c1, c2, wireColor); |  | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case e_hullShape: | 	case e_hullShape: | ||||||
| 	{ | 	{ | ||||||
| 		const b3HullShape* hs = (b3HullShape*)shape; | 		const b3HullShape* hs = (b3HullShape*)shape; | ||||||
| 		const b3Hull* hull = hs->m_hull; | 		const b3Hull* hull = hs->m_hull; | ||||||
|  | 		for (u32 i = 0; i < hull->edgeCount; i += 2) | ||||||
| 		for (u32 i = 0; i < hull->faceCount; ++i) |  | ||||||
| 		{ | 		{ | ||||||
| 			b3Vec3 polygon[B3_MAX_HULL_FEATURES]; | 			const b3HalfEdge* edge = hull->GetEdge(i); | ||||||
| 			u32 vCount = 0; | 			const b3HalfEdge* twin = hull->GetEdge(i + 1); | ||||||
| 			 | 			 | ||||||
| 			// Build convex polygon for loop | 			b3Vec3 p1 = xf * hull->vertices[edge->origin]; | ||||||
| 			const b3Face* face = hull->GetFace(i); | 			b3Vec3 p2 = xf * hull->vertices[twin->origin]; | ||||||
| 			const b3HalfEdge* begin = hull->GetEdge(face->edge); |  | ||||||
| 			const b3HalfEdge* edge = begin; |  | ||||||
| 			do |  | ||||||
| 			{ |  | ||||||
| 				polygon[vCount++] = xf * hull->GetVertex(edge->origin); |  | ||||||
| 				edge = hull->GetEdge(edge->next); |  | ||||||
| 			} while (edge != begin); |  | ||||||
|  |  | ||||||
| 			m_debugDraw->DrawPolygon(polygon, vCount, wireColor); | 			m_debugDraw->DrawSegment(p1, p2, wireColor); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case e_meshShape: | 	case e_meshShape: | ||||||
| @@ -214,14 +214,13 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const | |||||||
| 		const b3Mesh* mesh = ms->m_mesh; | 		const b3Mesh* mesh = ms->m_mesh; | ||||||
| 		for (u32 i = 0; i < mesh->triangleCount; ++i) | 		for (u32 i = 0; i < mesh->triangleCount; ++i) | ||||||
| 		{ | 		{ | ||||||
| 			const b3Triangle* triangle = mesh->triangles + i; | 			const b3Triangle* t = mesh->triangles + i; | ||||||
|  |  | ||||||
| 			b3Vec3 vs[3]; | 			b3Vec3 p1 = xf * mesh->vertices[t->v1]; | ||||||
| 			vs[0] = xf * mesh->vertices[triangle->v1]; | 			b3Vec3 p2 = xf * mesh->vertices[t->v2]; | ||||||
| 			vs[1] = xf * mesh->vertices[triangle->v2]; | 			b3Vec3 p3 = xf * mesh->vertices[t->v3]; | ||||||
| 			vs[2] = xf * mesh->vertices[triangle->v3]; |  | ||||||
|  |  | ||||||
| 			m_debugDraw->DrawPolygon(vs, 3, wireColor); | 			m_debugDraw->DrawTriangle(p1, p2, p3, wireColor); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ void b3MouseJoint::Draw(b3Draw* draw) const | |||||||
| 	b3Vec3 a = GetAnchorA(); | 	b3Vec3 a = GetAnchorA(); | ||||||
| 	b3Vec3 b = GetAnchorB(); | 	b3Vec3 b = GetAnchorB(); | ||||||
|  |  | ||||||
| 	draw->DrawPoint(a, green); | 	draw->DrawPoint(a, 4.0f, green); | ||||||
| 	draw->DrawPoint(b, red); | 	draw->DrawPoint(b, 4.0f, red); | ||||||
| 	draw->DrawSegment(a, b, yellow); | 	draw->DrawSegment(a, b, yellow); | ||||||
| } | } | ||||||
| @@ -162,7 +162,7 @@ void b3SphereJoint::Draw(b3Draw* draw) const | |||||||
| 	b3Vec3 a = GetAnchorA(); | 	b3Vec3 a = GetAnchorA(); | ||||||
| 	b3Vec3 b = GetAnchorB(); | 	b3Vec3 b = GetAnchorB(); | ||||||
| 	 | 	 | ||||||
| 	draw->DrawPoint(a, b3Color(1.0f, 0.0f, 0.0f)); | 	draw->DrawPoint(a, 4.0f, b3Color(1.0f, 0.0f, 0.0f)); | ||||||
| 	draw->DrawPoint(b, b3Color(0.0f, 1.0f, 0.0f)); | 	draw->DrawPoint(b, 4.0f, b3Color(0.0f, 1.0f, 0.0f)); | ||||||
| 	draw->DrawSegment(a, b, b3Color(1.0f, 1.0f, 0.0f)); | 	draw->DrawSegment(a, b, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -261,7 +261,7 @@ void b3SpringJoint::Draw(b3Draw* draw) const | |||||||
| 	b3Vec3 a = GetBodyA()->GetWorldPoint(m_localAnchorA); | 	b3Vec3 a = GetBodyA()->GetWorldPoint(m_localAnchorA); | ||||||
| 	b3Vec3 b = GetBodyB()->GetWorldPoint(m_localAnchorB); | 	b3Vec3 b = GetBodyB()->GetWorldPoint(m_localAnchorB); | ||||||
| 	 | 	 | ||||||
| 	draw->DrawPoint(a, green); | 	draw->DrawPoint(a, 4.0f, red); | ||||||
| 	draw->DrawPoint(b, green); | 	draw->DrawPoint(b, 4.0f, green); | ||||||
| 	draw->DrawSegment(a, b, blue); | 	draw->DrawSegment(a, b, blue); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -76,8 +76,8 @@ void b3CapsuleShape::ComputeMass(b3MassData* massData, float32 density) const | |||||||
| 		float32 volume = (2.0f / 3.0f) * B3_PI * r3; | 		float32 volume = (2.0f / 3.0f) * B3_PI * r3; | ||||||
| 		float32 mass = density * volume; | 		float32 mass = density * volume; | ||||||
| 		 | 		 | ||||||
| 		// Ic = Io + m * d^2 | 		// I = Ic + m * d^2 | ||||||
| 		// Io = Ic - m * d^2 | 		// Ic = I - m * d^2 | ||||||
|  |  | ||||||
| 		// Hemisphere inertia about the origin | 		// Hemisphere inertia about the origin | ||||||
| 		float32 Io = (2.0f / 5.0f) * mass * r2; | 		float32 Io = (2.0f / 5.0f) * mass * r2; | ||||||
| @@ -126,6 +126,8 @@ void b3CapsuleShape::ComputeMass(b3MassData* massData, float32 density) const | |||||||
| 	massData->center = Ic_Capsule.center; | 	massData->center = Ic_Capsule.center; | ||||||
| 	massData->mass = Ic_Capsule.mass; | 	massData->mass = Ic_Capsule.mass; | ||||||
| 	massData->I = Ic; | 	massData->I = Ic; | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void b3CapsuleShape::ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const  | void b3CapsuleShape::ComputeAABB(b3AABB3* aabb, const b3Transform& xf) const  | ||||||
| @@ -205,6 +207,33 @@ bool b3CapsuleShape::RayCast(b3RayCastOutput* output, const b3RayCastInput& inpu | |||||||
| 	// Check for short segment. | 	// Check for short segment. | ||||||
| 	if (dd < B3_EPSILON * B3_EPSILON) | 	if (dd < B3_EPSILON * B3_EPSILON) | ||||||
| 	{ | 	{ | ||||||
|  | 		float32 a = nn; | ||||||
|  | 		 | ||||||
|  | 		b3Vec3 m = A - P; | ||||||
|  | 		float32 b = b3Dot(m, n); | ||||||
|  | 		float32 c = b3Dot(m, m) - m_radius * m_radius; | ||||||
|  |  | ||||||
|  | 		float32 disc = b * b - a * c; | ||||||
|  |  | ||||||
|  | 		// Check for negative discriminant. | ||||||
|  | 		if (disc < 0.0f) | ||||||
|  | 		{ | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Find the minimum time of impact of the line with the sphere. | ||||||
|  | 		float32 t = -b - b3Sqrt(disc); | ||||||
|  |  | ||||||
|  | 		// Is the intersection point on the segment? | ||||||
|  | 		if (t > 0.0f && t <= input.maxFraction * a) | ||||||
|  | 		{ | ||||||
|  | 			// Finish solution. | ||||||
|  | 			t /= a; | ||||||
|  | 			output->fraction = t; | ||||||
|  | 			output->normal = b3Normalize(m + t * n); | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,7 +18,6 @@ | |||||||
|  |  | ||||||
| #include <bounce/dynamics/shapes/hull_shape.h> | #include <bounce/dynamics/shapes/hull_shape.h> | ||||||
| #include <bounce/collision/shapes/hull.h> | #include <bounce/collision/shapes/hull.h> | ||||||
| #include <bounce/common/template/array.h> |  | ||||||
|  |  | ||||||
| b3HullShape::b3HullShape() | b3HullShape::b3HullShape() | ||||||
| { | { | ||||||
|   | |||||||
| @@ -747,26 +747,28 @@ void qhHull::Draw(b3Draw* draw) const | |||||||
| 		b3Vec3 c = face->center; | 		b3Vec3 c = face->center; | ||||||
| 		b3Vec3 n = face->plane.normal; | 		b3Vec3 n = face->plane.normal; | ||||||
|  |  | ||||||
|  | 		b3StackArray<b3Vec3, 32> vs; | ||||||
|  | 		 | ||||||
|  | 		const qhHalfEdge* begin = face->edge; | ||||||
|  | 		const qhHalfEdge* edge = begin; | ||||||
|  | 		do | ||||||
|  | 		{ | ||||||
|  | 			vs.PushBack(edge->tail->position); | ||||||
|  | 			edge = edge->next; | ||||||
|  | 		} while (edge != begin); | ||||||
|  |  | ||||||
|  | 		draw->DrawSolidPolygon(n, vs.Elements(), vs.Count(), b3Color(1.0f, 1.0f, 1.0f, 0.5f)); | ||||||
|  |  | ||||||
| 		qhVertex* v = face->conflictList.head; | 		qhVertex* v = face->conflictList.head; | ||||||
| 		while (v) | 		while (v) | ||||||
| 		{ | 		{ | ||||||
| 			draw->DrawPoint(v->position, b3Color(1.0f, 1.0f, 0.0f)); | 			draw->DrawPoint(v->position, 4.0f, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			draw->DrawSegment(c, v->position, b3Color(1.0f, 1.0f, 0.0f)); | 			draw->DrawSegment(c, v->position, b3Color(1.0f, 1.0f, 0.0f)); | ||||||
| 			v = v->next; | 			v = v->next; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		draw->DrawSegment(c, c + n, b3Color(1.0f, 1.0f, 1.0f)); | 		draw->DrawSegment(c, c + n, b3Color(1.0f, 1.0f, 1.0f)); | ||||||
|  |  | ||||||
| 		b3StackArray<b3Vec3, 32> polygon; |  | ||||||
| 		qhHalfEdge* edge = face->edge; |  | ||||||
| 		do |  | ||||||
| 		{ |  | ||||||
| 			polygon.PushBack(edge->tail->position); |  | ||||||
| 			edge = edge->next; |  | ||||||
| 		} while (edge != face->edge); |  | ||||||
|  |  | ||||||
| 		draw->DrawSolidPolygon(polygon.Elements(), polygon.Count(), b3Color(0.0f, 0.0f, 1.0f, 1.0f)); |  | ||||||
| 		 |  | ||||||
| 		face = face->next; | 		face = face->next; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -261,13 +261,13 @@ void Interface() | |||||||
| 	ImGui::Text("Step"); | 	ImGui::Text("Step"); | ||||||
|  |  | ||||||
| 	ImGui::Text("Hertz"); | 	ImGui::Text("Hertz"); | ||||||
| 	ImGui::SliderFloat("##Hertz", &g_settings.hertz, 0.0f, 240.0f, "%.4f"); | 	ImGui::SliderFloat("##Hertz", &g_settings.hertz, 0.0f, 240.0f, "%.1f"); | ||||||
| 	ImGui::Text("Velocity Iterations"); | 	ImGui::Text("Velocity Iterations"); | ||||||
| 	ImGui::SliderInt("##Velocity Iterations", &g_settings.velocityIterations, 0, 50); | 	ImGui::SliderInt("##Velocity Iterations", &g_settings.velocityIterations, 0, 50); | ||||||
| 	ImGui::Text("Position Iterations"); | 	ImGui::Text("Position Iterations"); | ||||||
| 	ImGui::SliderInt("#Position Iterations", &g_settings.positionIterations, 0, 50); | 	ImGui::SliderInt("#Position Iterations", &g_settings.positionIterations, 0, 50); | ||||||
| 	ImGui::Checkbox("Warm Start", &g_settings.warmStart); |  | ||||||
| 	ImGui::Checkbox("Sleep", &g_settings.sleep); | 	ImGui::Checkbox("Sleep", &g_settings.sleep); | ||||||
|  | 	ImGui::Checkbox("Warm Start", &g_settings.warmStart); | ||||||
| 	//ImGui::Checkbox("Convex Cache", &g_settings.convexCache); | 	//ImGui::Checkbox("Convex Cache", &g_settings.convexCache); | ||||||
|  |  | ||||||
| 	if (ImGui::Button("Play/Pause", buttonSize)) | 	if (ImGui::Button("Play/Pause", buttonSize)) | ||||||
| @@ -280,13 +280,12 @@ void Interface() | |||||||
| 		g_settings.singleStep = true; | 		g_settings.singleStep = true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ImGui::PopItemWidth(); |  | ||||||
|  |  | ||||||
| 	ImGui::Separator(); | 	ImGui::Separator(); | ||||||
|  |  | ||||||
| 	ImGui::Text("View"); | 	ImGui::Text("View"); | ||||||
| 	ImGui::Checkbox("Grid", &g_settings.drawGrid); | 	ImGui::Checkbox("Grid", &g_settings.drawGrid); | ||||||
| 	ImGui::Checkbox("Polygons", &g_settings.drawShapes); | 	ImGui::Checkbox("Vertices and Edges", &g_settings.drawVerticesEdges); | ||||||
|  | 	ImGui::Checkbox("Faces", &g_settings.drawFaces); | ||||||
| 	ImGui::Checkbox("Center of Masses", &g_settings.drawCenterOfMasses); | 	ImGui::Checkbox("Center of Masses", &g_settings.drawCenterOfMasses); | ||||||
| 	ImGui::Checkbox("Bounding Boxes", &g_settings.drawBounds); | 	ImGui::Checkbox("Bounding Boxes", &g_settings.drawBounds); | ||||||
| 	ImGui::Checkbox("Joints", &g_settings.drawJoints); | 	ImGui::Checkbox("Joints", &g_settings.drawJoints); | ||||||
| @@ -301,6 +300,36 @@ void Interface() | |||||||
|  |  | ||||||
| void Step() | void Step() | ||||||
| { | { | ||||||
|  | 	if (g_settings.drawGrid) | ||||||
|  | 	{ | ||||||
|  | 		int n = 20; | ||||||
|  |  | ||||||
|  | 		b3Vec3 t; | ||||||
|  | 		t.x = -0.5f * float32(n); | ||||||
|  | 		t.y = 0.0f; | ||||||
|  | 		t.z = -0.5f * float32(n); | ||||||
|  |  | ||||||
|  | 		b3Color color(0.5f, 0.5f, 0.5f, 1.0f); | ||||||
|  | 		for (int i = 0; i < n; i += 1) | ||||||
|  | 		{ | ||||||
|  | 			for (int j = 0; j < n; j += 1) | ||||||
|  | 			{ | ||||||
|  | 				b3Vec3 vs[4]; | ||||||
|  | 				vs[0] = b3Vec3((float)i, 0.0f, (float)j); | ||||||
|  | 				vs[1] = b3Vec3((float)i, 0.0f, (float)j + 1); | ||||||
|  | 				vs[2] = b3Vec3((float)i + 1, 0.0f, (float)j + 1); | ||||||
|  | 				vs[3] = b3Vec3((float)i + 1, 0.0f, (float)j); | ||||||
|  |  | ||||||
|  | 				for (u32 k = 0; k < 4; ++k) | ||||||
|  | 				{ | ||||||
|  | 					vs[k] += t; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				g_debugDraw->DrawPolygon(vs, 4, color); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if (g_settings.testID != g_settings.lastTestID) | 	if (g_settings.testID != g_settings.lastTestID) | ||||||
| 	{ | 	{ | ||||||
| 		delete g_test; | 		delete g_test; | ||||||
| @@ -308,7 +337,9 @@ void Step() | |||||||
| 		g_test = g_tests[g_settings.testID].create(); | 		g_test = g_tests[g_settings.testID].create(); | ||||||
| 		g_settings.pause = true; | 		g_settings.pause = true; | ||||||
| 	} | 	} | ||||||
|  | 	 | ||||||
| 	g_test->Step();	 | 	g_test->Step();	 | ||||||
|  | 	g_debugDraw->Draw(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Run() | void Run() | ||||||
| @@ -320,9 +351,12 @@ void Run() | |||||||
| 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||||
| 	glEnable(GL_BLEND); | 	glEnable(GL_BLEND); | ||||||
|  |  | ||||||
| 	glClearColor(0.3f, 0.3f, 0.3f, 1.0f); | 	glClearColor(0.2f, 0.2f, 0.2f, 1.0f); | ||||||
| 	glClearDepth(1.0f); | 	glClearDepth(1.0f); | ||||||
|  |  | ||||||
|  | 	double t1 = glfwGetTime(); | ||||||
|  | 	double frameTime = 0.0; | ||||||
|  |  | ||||||
| 	while (glfwWindowShouldClose(g_window) == 0) | 	while (glfwWindowShouldClose(g_window) == 0) | ||||||
| 	{ | 	{ | ||||||
| 		int width, height; | 		int width, height; | ||||||
| @@ -335,62 +369,19 @@ void Run() | |||||||
| 		 | 		 | ||||||
| 		ImGui_ImplGlfwGL3_NewFrame(); | 		ImGui_ImplGlfwGL3_NewFrame(); | ||||||
| 		 | 		 | ||||||
| 		if (g_settings.drawGrid) | 		ImGui::SetNextWindowPos(ImVec2(0, 0)); | ||||||
| 		{ | 		ImGui::SetNextWindowSize(ImVec2((float)g_camera.m_width, (float)g_camera.m_height)); | ||||||
| 			int n = 20; | 		ImGui::Begin("Overlay", NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); | ||||||
|  | 		ImGui::SetCursorPos(ImVec2(5, (float)g_camera.m_height - 20)); | ||||||
| 			b3Vec3 t; | 		ImGui::Text("%.1f ms", 1000.0 * frameTime); | ||||||
| 			t.x = -0.5f * float32(n); | 		ImGui::End(); | ||||||
| 			t.y = 0.0f; |  | ||||||
| 			t.z = -0.5f * float32(n); |  | ||||||
|  |  | ||||||
| 			b3Color color(1.0f, 1.0f, 1.0f, 1.0f); |  | ||||||
| 			for (int i = 0; i < n; i += 1) |  | ||||||
| 			{ |  | ||||||
| 				for (int j = 0; j < n; j += 1) |  | ||||||
| 				{ |  | ||||||
| 					b3Vec3 vs[4]; |  | ||||||
| 					vs[0] = b3Vec3((float)i, 0.0f, (float)j); |  | ||||||
| 					vs[1] = b3Vec3((float)i, 0.0f, (float)j + 1); |  | ||||||
| 					vs[2] = b3Vec3((float)i + 1, 0.0f, (float)j + 1); |  | ||||||
| 					vs[3] = b3Vec3((float)i + 1, 0.0f, (float)j); |  | ||||||
|  |  | ||||||
| 					for (u32 k = 0; k < 4; ++k) |  | ||||||
| 					{ |  | ||||||
| 						vs[k] += t; |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					g_debugDraw->DrawPolygon(vs, 4, color); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			b3Color color2(0.0f, 0.0f, 0.0f); |  | ||||||
|  |  | ||||||
| 			{ |  | ||||||
| 				b3Vec3 p1(t.x, 0.005f, 0.0f); |  | ||||||
| 				b3Vec3 p2(-t.x, 0.005f, 0.0f); |  | ||||||
|  |  | ||||||
| 				g_debugDraw->DrawSegment(p1, p2, color2); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			{ |  | ||||||
| 				b3Vec3 p1(0.0f, 0.005f, t.x); |  | ||||||
| 				b3Vec3 p2(0.0f, 0.005f, -t.x); |  | ||||||
|  |  | ||||||
| 				g_debugDraw->DrawSegment(p1, p2, color2); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		 |  | ||||||
| 		Step(); |  | ||||||
| 		 |  | ||||||
| 		g_debugDraw->Submit(); |  | ||||||
|  |  | ||||||
| 		if (g_settings.drawShapes) |  | ||||||
| 		{ |  | ||||||
| 			g_debugDraw->Submit(g_test->m_world); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Interface(); | 		Interface(); | ||||||
|  | 		Step(); | ||||||
|  |  | ||||||
|  | 		double t = glfwGetTime(); | ||||||
|  | 		frameTime = t - t1; | ||||||
|  | 		t1 = t; | ||||||
|  |  | ||||||
| 		ImGui::Render(); | 		ImGui::Render(); | ||||||
|  |  | ||||||
| @@ -413,13 +404,17 @@ int main(int argc, char** args) | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	// Create g_window | 	// Create window | ||||||
| 	extern b3Version b3_version; | 	extern b3Version b3_version; | ||||||
| 	char title[256]; | 	char title[256]; | ||||||
| 	sprintf(title, "Bounce Testbed Version %d.%d.%d", b3_version.major, b3_version.minor, b3_version.revision); | 	sprintf(title, "Bounce Testbed Version %d.%d.%d", b3_version.major, b3_version.minor, b3_version.revision); | ||||||
|  |  | ||||||
| 	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | #if defined(__APPLE__) | ||||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | 	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); | ||||||
|  | 	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); | ||||||
|  | 	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); | ||||||
|  | 	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | ||||||
|  | #endif | ||||||
| 		 | 		 | ||||||
| 	g_window = glfwCreateWindow(1024, 768, title, NULL, NULL); | 	g_window = glfwCreateWindow(1024, 768, title, NULL, NULL); | ||||||
| 	if (g_window == NULL) | 	if (g_window == NULL) | ||||||
|   | |||||||
| @@ -364,9 +364,27 @@ void Test::Step() | |||||||
| 	m_maxProfile.solver.solveVelocity = b3Max(m_maxProfile.solver.solveVelocity, m_profile.solver.solveVelocity); | 	m_maxProfile.solver.solveVelocity = b3Max(m_maxProfile.solver.solveVelocity, m_profile.solver.solveVelocity); | ||||||
| 	m_maxProfile.solver.solvePosition = b3Max(m_maxProfile.solver.solvePosition, m_profile.solver.solvePosition); | 	m_maxProfile.solver.solvePosition = b3Max(m_maxProfile.solver.solvePosition, m_profile.solver.solvePosition); | ||||||
|  |  | ||||||
|  | 	// Draw World | ||||||
|  | 	u32 drawFlags = 0; | ||||||
|  | 	drawFlags += g_settings.drawBounds * b3Draw::e_aabbsFlag; | ||||||
|  | 	drawFlags += g_settings.drawVerticesEdges * b3Draw::e_shapesFlag; | ||||||
|  | 	drawFlags += g_settings.drawCenterOfMasses * b3Draw::e_centerOfMassesFlag; | ||||||
|  | 	drawFlags += g_settings.drawJoints * b3Draw::e_jointsFlag; | ||||||
|  | 	drawFlags += g_settings.drawContactPoints * b3Draw::e_contactPointsFlag; | ||||||
|  | 	drawFlags += g_settings.drawContactNormals * b3Draw::e_contactNormalsFlag; | ||||||
|  | 	drawFlags += g_settings.drawContactTangents * b3Draw::e_contactTangentsFlag; | ||||||
|  |  | ||||||
|  | 	g_debugDraw->SetFlags(drawFlags); | ||||||
|  | 	m_world.DebugDraw(); | ||||||
|  | 	g_debugDraw->Draw(); | ||||||
|  | 	 | ||||||
|  | 	if (g_settings.drawFaces) | ||||||
|  | 	{ | ||||||
|  | 		g_debugDraw->Draw(m_world); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// Draw Statistics | 	// Draw Statistics | ||||||
| 	ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); | 	ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); | ||||||
| 	//ImGui::SetNextWindowSize(ImVec2(250.0f, g_camera.m_height)); |  | ||||||
| 	ImGui::Begin("Log", NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); | 	ImGui::Begin("Log", NULL, ImVec2(0, 0), 0.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoScrollbar); | ||||||
|  |  | ||||||
| 	if (g_settings.drawStats) | 	if (g_settings.drawStats) | ||||||
| @@ -405,19 +423,6 @@ void Test::Step() | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ImGui::End(); | 	ImGui::End(); | ||||||
|  |  | ||||||
| 	u32 drawFlags = 0; |  | ||||||
| 	drawFlags += g_settings.drawBounds * b3Draw::e_aabbsFlag; |  | ||||||
| 	drawFlags += g_settings.drawShapes * b3Draw::e_shapesFlag; |  | ||||||
| 	drawFlags += g_settings.drawCenterOfMasses * b3Draw::e_centerOfMassesFlag; |  | ||||||
| 	drawFlags += g_settings.drawJoints * b3Draw::e_jointsFlag; |  | ||||||
| 	drawFlags += g_settings.drawContactPoints * b3Draw::e_contactPointsFlag; |  | ||||||
| 	drawFlags += g_settings.drawContactNormals * b3Draw::e_contactNormalsFlag; |  | ||||||
| 	drawFlags += g_settings.drawContactTangents * b3Draw::e_contactTangentsFlag; |  | ||||||
|  |  | ||||||
| 	g_debugDraw->SetFlags(drawFlags); |  | ||||||
|  |  | ||||||
| 	m_world.DebugDraw(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void Test::MouseMove(const Ray3& pw) | void Test::MouseMove(const Ray3& pw) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user