Advertisement
Guest User

Untitled

a guest
Dec 2nd, 2016
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 46.60 KB | None | 0 0
  1. #include <windows.h>
  2. #include <gl/gl.h>
  3. #include <stdio.h>
  4. #include <stdint.h>
  5. #include <stddef.h>
  6. #include <assert.h>
  7.  
  8. #include <glm\glm.hpp>
  9. #include <glm\gtc\matrix_transform.hpp>
  10. #include <glm\gtx\norm.hpp>
  11. #include <glm\gtx\matrix_decompose.hpp>
  12. #include <glm\gtx\euler_angles.hpp>
  13. using namespace glm;
  14.  
  15. static const float Pi32 = glm::pi<float>();
  16. static const float Tau32 = Pi32 * 2.0f;
  17.  
  18. typedef int32_t B32;
  19.  
  20. #define EDIT_MODE 0
  21.  
  22. #define SwapPtr(type, a, b) { void* tmp = a; a = b; b = (type*)tmp; }
  23. #define ArrayCount(Array) (sizeof(Array) / sizeof((Array)[0]))
  24.  
  25. inline vec2 Cross(const vec2 &a, float s) {
  26.     return vec2(s * a.y, -s * a.x);
  27. }
  28. inline vec2 Cross(float s, const vec2 &a) {
  29.     return vec2(-s * a.y, s * a.x);
  30. }
  31. inline float Cross(const vec2 &a, const vec2 &b) {
  32.     return a.x * b.y - a.y * b.x;
  33. }
  34. inline float Clamp(float min, float value, float max) {
  35.     float result = value;
  36.     if (result < min) {
  37.         result = min;
  38.     } else if (result > max) {
  39.         result = max;
  40.     }
  41.     return(result);
  42. }
  43.  
  44. struct RenderState {
  45.     vec2 gameSize;
  46.     ivec2 screenSize;
  47.     ivec2 viewportSize;
  48.     ivec2 viewportOffset;
  49.     float renderScale;
  50.     float cameraScale;
  51.     vec2 cameraOffset;
  52. };
  53.  
  54. struct ButtonState {
  55.     int halfTransitionCount;
  56.     B32 endedDown;
  57. };
  58. inline B32 WasDown(ButtonState state) {
  59.     B32 result = ((state.halfTransitionCount > 1) || ((state.halfTransitionCount == 1) && (state.endedDown)));
  60.     return(result);
  61. }
  62. inline B32 IsDown(ButtonState state) {
  63.     B32 result = state.endedDown;
  64.     return(result);
  65. }
  66.  
  67. static const int MouseButton_Count = 5;
  68. struct MouseState {
  69.     vec2 pos;
  70.     union {
  71.         ButtonState buttons[MouseButton_Count];
  72.         struct {
  73.             ButtonState leftMouseButton;
  74.             ButtonState middleMouseButton;
  75.             ButtonState rightMouseButton;
  76.             ButtonState xMouseButton1;
  77.             ButtonState xMouseButton2;
  78.         };
  79.     };
  80. };
  81.  
  82. static const int KeyboardButton_Count = 4;
  83. struct KeyboardState {
  84.     union {
  85.         ButtonState buttons[KeyboardButton_Count];
  86.         struct {
  87.             ButtonState space;
  88.             ButtonState f1;
  89.             ButtonState q;
  90.             ButtonState e;
  91.         };
  92.     };
  93. };
  94.  
  95. struct InputState {
  96.     MouseState mouse;
  97.     KeyboardState keyboard;
  98. };
  99.  
  100. inline vec2 Unproject(RenderState *renderState, int x, int y) {
  101.     vec2 result = {};
  102.     if (renderState->renderScale > 0) {
  103.         result.x = (float)((x - renderState->viewportOffset.x) / (renderState->renderScale * renderState->cameraScale));
  104.         result.y = (float)((y - renderState->viewportOffset.y) / (renderState->renderScale * renderState->cameraScale));
  105.         result.x -= (renderState->gameSize.x * 0.5f / renderState->cameraScale) + renderState->cameraOffset.x;
  106.         result.y -= (renderState->gameSize.y * 0.5f / renderState->cameraScale) + renderState->cameraOffset.y;
  107.     }
  108.     return (result);
  109. }
  110.  
  111. static const float GameWidthInMeters = 10.0f;
  112. static const float GameAspect = 16.0f / 9.0f;
  113.  
  114. struct Transform {
  115.     vec2 translation;
  116.     mat2 rotation;
  117. };
  118. inline vec2 operator *(const vec2 &v, const Transform &t) {
  119.     vec2 result = t.rotation * v + t.translation;
  120.     return(result);
  121. }
  122.  
  123. enum ShapeType {
  124.     ShapeType_Plane = 1,
  125.     ShapeType_Circle = 2,
  126.     ShapeType_Polygon = 3,
  127. };
  128. struct PlaneShape {
  129.     float visualLength;
  130.     // Normal is computed from rotation
  131.     // Distance is computed from position
  132. };
  133. struct CircleShape {
  134.     float radius;
  135. };
  136. static const int MaxPolygonVertexCount = 16;
  137. struct PolygonShape {
  138.     vec2 localVerts[MaxPolygonVertexCount];
  139.     int numVerts;
  140. };
  141. struct Shape {
  142.     ShapeType type;
  143.     union {
  144.         CircleShape circle;
  145.         PlaneShape plane;
  146.         PolygonShape poly;
  147.     };
  148. };
  149.  
  150. struct MassData {
  151.     vec2 centroid;
  152.     float mass;
  153.     float inertia;
  154. };
  155.  
  156. enum BodyType {
  157.     Static = 0,
  158.     Dynamic = 1,
  159. };
  160. struct Body {
  161.     vec2 position;
  162.     float rotation;
  163.     vec2 velocity;
  164.     float angularVelocity;
  165.     vec2 force;
  166.     float torque;
  167.     vec2 centroid;
  168.     BodyType type;
  169.     Shape shape;
  170.     float mass;
  171.     float invMass;
  172.     float inertia;
  173.     float invInertia;
  174. };
  175.  
  176. struct Contact {
  177.     vec2 normal;
  178.     vec2 pointOnA;
  179.     vec2 relativeArmA;
  180.     vec2 relativeArmB;
  181.     float distance;
  182.     float accumulatedNormalImpulse;
  183.     float accumulatedTangentImpulse;
  184.     float normalMassRatio;
  185.     float tangentMassRatio;
  186. };
  187.  
  188. struct Face {
  189.     int index;
  190.     vec2 points[2];
  191. };
  192.  
  193. struct Arbiter {
  194.     Contact contacts[2];
  195.     int numContacts;
  196.     Body *bodyA;
  197.     Body *bodyB;
  198.     float friction;
  199. };
  200.  
  201. #define CONTACT_GENERATOR(name) int name(const Transform &transformA, Shape *shapeA, const Transform &transformB, Shape *shapeB, Contact *contacts)
  202. typedef CONTACT_GENERATOR(generate_contacts);
  203.  
  204. static const int MaxBodyCount = 1024;
  205. static const int MaxArbiterCount = MaxBodyCount * 2;
  206. static const int SolverIterationCount = 4;
  207.  
  208. static const float InteractionRadius = 0.4f;
  209.  
  210. enum InteractionType {
  211.     InteractionType_None = 0,
  212.     InteractionType_MoveRotate = 1,
  213. };
  214.  
  215. struct InteractionNone {
  216. };
  217.  
  218. struct InteractionDragging {
  219.     vec2 startPos;
  220. };
  221.  
  222. struct InteractionState {
  223.     Body *hotBody;
  224.     Body *activeBody;
  225.     InteractionType type;
  226.     union {
  227.         InteractionNone none;
  228.         InteractionDragging dragging;
  229.     };
  230. };
  231.  
  232. struct World {
  233.     vec2 boundaryExt;
  234.     Body* bodies;
  235.     int numBodies;
  236.     vec2 gravity;
  237.     Arbiter *arbiters;
  238.     int numArbiters;
  239.     bool stepEnabled;
  240.     bool step;
  241.     InteractionState interaction;
  242. };
  243.  
  244. inline Body *AddBody(World *world, BodyType type, vec2 pos, float rotation = 0.0f) {
  245.     assert(world->numBodies < MaxBodyCount);
  246.     Body *result = &world->bodies[world->numBodies++];
  247.     memset(result, 0, sizeof(Body));
  248.     result->type = type;
  249.     result->position = pos;
  250.     result->rotation = rotation;
  251.     return(result);
  252. }
  253.  
  254. inline void ApplyMassData(Body *body, MassData *massData) {
  255.     if (body->type == BodyType::Dynamic) {
  256.         body->mass = massData->mass;
  257.         body->inertia = massData->inertia;
  258.         body->invMass = body->mass > 0 ? (1.0f / body->mass) : 0;
  259.         body->invInertia = body->inertia > 0 ? (1.0f / body->inertia) : 0;
  260.         body->centroid = massData->centroid;
  261.     } else {
  262.         body->mass = body->inertia = 0;
  263.         body->invMass = body->invInertia = 0;
  264.         body->centroid = vec2(0, 0);
  265.     }
  266. }
  267.  
  268. inline void DefinePlane(Body *body, float visualLength = 10.0f) {
  269.     memset(&body->shape, 0, sizeof(Shape));
  270.     body->shape.type = ShapeType::ShapeType_Plane;
  271.     body->shape.plane.visualLength = visualLength;
  272.     body->mass = body->invMass = body->inertia = body->invInertia = 0;
  273. }
  274.  
  275. inline MassData ComputeCircleMassData(CircleShape *circle, float density) {
  276.     MassData result = {};
  277.     result.mass = Pi32 * circle->radius * circle->radius * density;
  278.     result.centroid = vec2(0);
  279.     result.inertia = result.mass * (0.5f * circle->radius * circle->radius + glm::length2(result.centroid));
  280.     return(result);
  281. }
  282. inline void DefineCircle(Body *body, float radius, float density = 1.0f) {
  283.     memset(&body->shape, 0, sizeof(Shape));
  284.     body->shape.type = ShapeType::ShapeType_Circle;
  285.     body->shape.circle.radius = radius;
  286.     MassData massData = ComputeCircleMassData(&body->shape.circle, density);
  287.     ApplyMassData(body, &massData);
  288. }
  289.  
  290. static vec2 GetPolygonCentroid(int numVerts, vec2 *verts) {
  291.     const float inv3 = 1.0f / 3.0f;
  292.     vec2 result = vec2(0);
  293.     float area = 0.0f;
  294.     for (int vertIndex = 0; vertIndex < numVerts; vertIndex++) {
  295.         vec2 p0 = verts[vertIndex];
  296.         vec2 p1 = verts[(vertIndex + 1) % numVerts];
  297.         float d = (p0.x * p1.y) - (p1.x * p0.y);
  298.         area += d * 0.5f;
  299.         result += (p0 + p1) * d * inv3;
  300.     }
  301.     if (area > 0) {
  302.         result *= (1.0f / area);
  303.     }
  304.     return(result);
  305. }
  306. static MassData ComputePolygonMassData(PolygonShape *polygon, float density) {
  307.     float area = 0.0f;
  308.     const float inv3 = 1.0f / 3.0f;
  309.     float I = 0.0f;
  310.     for (int vertIndex = 0; vertIndex < polygon->numVerts; vertIndex++) {
  311.         vec2 p0 = polygon->localVerts[vertIndex];
  312.         vec2 p1 = polygon->localVerts[(vertIndex + 1) % polygon->numVerts];
  313.         float d = (p0.x * p1.y) - (p1.x * p0.y);
  314.         float triangleArea = d * 0.5f;
  315.         area += triangleArea;
  316.         float ex1 = p0.x, ey1 = p0.y;
  317.         float ex2 = p1.x, ey2 = p1.y;
  318.         float intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2;
  319.         float inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2;
  320.         I += (0.25f * inv3 * d) * (intx2 + inty2);
  321.     }
  322.     MassData result = {};
  323.     result.mass = area * density;
  324.     result.centroid = GetPolygonCentroid(polygon->numVerts, &polygon->localVerts[0]);
  325.     result.inertia = I * density + (result.mass * glm::length2(result.centroid));
  326.     return(result);
  327. }
  328. inline void DefineBox(Body *body, vec2 radius, float density = 1.0f) {
  329.     memset(&body->shape, 0, sizeof(Shape));
  330.     body->shape.type = ShapeType::ShapeType_Polygon;
  331.     body->shape.poly.numVerts = 4;
  332.     body->shape.poly.localVerts[0] = vec2(radius.x, radius.y);
  333.     body->shape.poly.localVerts[1] = vec2(-radius.x, radius.y);
  334.     body->shape.poly.localVerts[2] = vec2(-radius.x, -radius.y);
  335.     body->shape.poly.localVerts[3] = vec2(radius.x, -radius.y);
  336.     MassData massData = ComputePolygonMassData(&body->shape.poly, density);
  337.     ApplyMassData(body, &massData);
  338. }
  339.  
  340. // -----------------------------------------
  341. // INITIALIZATION
  342. // -----------------------------------------
  343.  
  344. static void GameInit(World *world) {
  345.     memset(world, 0, sizeof(World));
  346.     world->stepEnabled = true;
  347.     world->bodies = (Body *)malloc(sizeof(Body) * MaxBodyCount);
  348.     world->arbiters = (Arbiter *)malloc(sizeof(Arbiter) * MaxArbiterCount);
  349.     world->boundaryExt = vec2(GameWidthInMeters, GameWidthInMeters / GameAspect) * 0.5f;
  350.     world->gravity = vec2(0, -10);
  351.  
  352.     DefinePlane(AddBody(world, BodyType::Static, vec2(0, -2), glm::radians(90.0f)));
  353.     //DefinePlane(AddBody(world, BodyType::Static, vec2(-world->boundaryExt.x, 0), glm::radians(0.0f)));
  354.     //DefinePlane(AddBody(world, BodyType::Static, vec2(world->boundaryExt.x, 0), glm::radians(180.0f)));
  355.     //DefineBox(AddBody(world, BodyType::Static, vec2(0, -2)), vec2(1, 1));
  356.  
  357.     float radius = 0.5f;
  358.     float spaceBetween = 0.1f;
  359.     const int numDynamicBodies = 2;
  360.     float sumDistance = radius * 2 * numDynamicBodies + (spaceBetween * numDynamicBodies - 1);
  361.     for (int i = 0; i < numDynamicBodies; ++i) {
  362.         float x = 0;
  363.         float y = 0 + i * radius * 2 + i * spaceBetween;
  364.         //DefineCircle(AddBody(world, BodyType::Dynamic, vec2(x, y)), 0.5f);
  365.         DefineBox(AddBody(world, BodyType::Dynamic, vec2(x, y)), vec2(radius));
  366.     }
  367. }
  368.  
  369. // -----------------------------------------
  370. // UPDATE
  371. // -----------------------------------------
  372.  
  373. static vec2 GetSupportPoint(vec2 normal, int vertexCount, vec2 *vertices) {
  374.     vec2 result = vertices[0];
  375.     float distance = glm::dot(result, normal);
  376.     for (int vertexIndex = 1; vertexIndex < vertexCount; ++vertexIndex) {
  377.         vec2 v = vertices[vertexIndex];
  378.         float p = glm::dot(v, normal);
  379.         if (p > distance) {
  380.             distance = p;
  381.             result = v;
  382.         }
  383.     }
  384.     return (result);
  385. }
  386.  
  387. static Face GetFace(int vertexCount, vec2 *verts, vec2 normal) {
  388.     int firstIndex = 0;
  389.     float firstDistance = glm::dot(verts[0], normal);
  390.     for (int vertexIndex = 1; vertexIndex < vertexCount; vertexIndex++) {
  391.         vec2 v = verts[vertexIndex];
  392.         float p = glm::dot(v, normal);
  393.         if (p > firstDistance) {
  394.             firstDistance = p;
  395.             firstIndex = vertexIndex;
  396.         }
  397.     }
  398.  
  399.     int secondIndex = -1;
  400.     float secondDistance = 0;
  401.     for (int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
  402.         if (vertexIndex != firstIndex) {
  403.             vec2 v = verts[vertexIndex];
  404.             float p = glm::dot(v, normal);
  405.             if (secondIndex == -1 || p > secondDistance) {
  406.                 secondDistance = p;
  407.                 secondIndex = vertexIndex;
  408.             }
  409.         }
  410.     }
  411.     assert(secondIndex > -1);
  412.     Face result = {};
  413.     result.index = firstIndex;
  414.     result.points[0] = verts[firstIndex];
  415.     result.points[1] = verts[secondIndex];
  416.     return (result);
  417. }
  418.  
  419. struct ClipResult {
  420.     vec2 points[2];
  421. };
  422. static ClipResult Clip(vec2 normal, vec2 ref1, vec2 ref2, vec2 inc1, vec2 inc2) {
  423.     vec2 tangent = Cross(normal, 1.0f);
  424.     vec2 segmentDistance = inc2 - inc1;
  425.     vec2 segmentToLine0 = ref1 - inc1;
  426.     vec2 segmentToLine1 = ref2 - inc1;
  427.     float d0 = glm::dot(segmentToLine0, tangent);
  428.     float d1 = glm::dot(segmentToLine1, tangent);
  429.     float f0 = d0 / glm::dot(segmentDistance, tangent);
  430.     float f1 = d1 / glm::dot(segmentDistance, tangent);
  431.     ClipResult result = {};
  432.     result.points[0] = inc1 + segmentDistance * Clamp(0, f0, 1);
  433.     result.points[1] = inc1 + segmentDistance * Clamp(0, f1, 1);
  434.     return (result);
  435. }
  436.  
  437. struct SATResult {
  438.     float distance;
  439.     vec2 normal;
  440. };
  441. static SATResult QuerySAT(const Transform &transformA, const Transform &transformB, int numVertsA, vec2 *localVertsA, int numVertsB, vec2 *localVertsB) {
  442.     SATResult result = {};
  443.  
  444.     mat2 rotAToB = transformA.rotation * glm::transpose(transformB.rotation);
  445.  
  446.     B32 first = true;
  447.     for (int vertIndexA = 0; vertIndexA < numVertsA; vertIndexA++) {
  448.         // Create normal for A
  449.         vec2 v0 = localVertsA[vertIndexA];
  450.         vec2 v1 = localVertsA[(vertIndexA + 1) % numVertsA];
  451.         vec2 t = glm::normalize(v1 - v0);
  452.         vec2 localNormalA = Cross(t, 1.0f);
  453.  
  454.         // Bring normal A into its own space
  455.         vec2 normalForA = transformA.rotation * localNormalA;
  456.         // Bring normal A into the space of B
  457.         vec2 normalForB = rotAToB * localNormalA;
  458.  
  459.         // Get support point for B
  460.         vec2 supportPointB = GetSupportPoint(-normalForB, numVertsB, localVertsB);
  461.  
  462.         // Get closest distance
  463.         vec2 pA = v0 * transformA;
  464.         vec2 pB = supportPointB * transformB;
  465.         vec2 pAB = pB - pA;
  466.         float proj = glm::dot(pAB, normalForA);
  467.  
  468.         // Record axis of minimum penetration
  469.         if (first || proj > result.distance) {
  470.             first = false;
  471.             result.normal = localNormalA;
  472.             result.distance = proj;
  473.         }
  474.     }
  475.     return(result);
  476. }
  477.  
  478. static vec2 GetClosestPointOnLineSegment(vec2 point, vec2 a, vec2 b, float *region) {
  479.     vec2 lineAB = b - a;
  480.     vec2 pointToLine = point - a;
  481.     *region = glm::dot(pointToLine, lineAB) / glm::length2(lineAB);
  482.     float percentage = Clamp(0, *region, 1);
  483.     vec2 result = a + lineAB * percentage;
  484.     return (result);
  485. }
  486.  
  487. struct ManifoldInput {
  488.     B32 flip;
  489.     vec2 localNormalA;
  490.     Transform transformA;
  491.     Transform transformB;
  492.     mat2 rotAtoB;
  493.     vec2 *localVertsA;
  494.     vec2 *localVertsB;
  495.     int numVertsA;
  496.     int numVertsB;
  497. };
  498. inline ManifoldInput MakeInputManifold(B32 flip, vec2 localNormalA, Transform transformA, Transform transformB, int numVertsA, vec2 *localVertsA, int numVertsB, vec2 *localVertsB) {
  499.     ManifoldInput result = {};
  500.     result.flip = flip;
  501.     result.localNormalA = localNormalA;
  502.     result.transformA = transformA;
  503.     result.transformB = transformB;
  504.     result.localVertsA = localVertsA;
  505.     result.localVertsB = localVertsB;
  506.     result.numVertsA = numVertsA;
  507.     result.numVertsB = numVertsB;
  508.     result.rotAtoB = transformA.rotation * glm::transpose(transformB.rotation);
  509.     return (result);
  510. }
  511.  
  512. struct ManifoldOutput {
  513.     vec2 points[2];
  514.     float distances[2];
  515.     int features[2];
  516.     vec2 normal;
  517.     int count;
  518. };
  519.  
  520. static CONTACT_GENERATOR(ContactGeneratorPlaneCircle) {
  521.     int result = 0;
  522.  
  523.     PlaneShape *plane = &shapeA->plane;
  524.     CircleShape *circle = &shapeB->circle;
  525.  
  526.     vec2 posA = transformA.translation;
  527.     vec2 posB = transformB.translation;
  528.     vec2 normal = transformA.rotation[0];
  529.  
  530.     vec2 distanceToPlane = posA - posB;
  531.     float projDistance = glm::dot(distanceToPlane, normal);
  532.     float projRadius = -circle->radius;
  533.     float d = projRadius - projDistance;
  534.     vec2 pointOnA = posB + normal * projDistance;
  535.  
  536.     Contact *contact = &contacts[result++];
  537.     *contact = {};
  538.     contact->normal = normal;
  539.     contact->distance = d;
  540.     contact->pointOnA = pointOnA;
  541.  
  542.     return(result);
  543. }
  544.  
  545. static CONTACT_GENERATOR(ContactGeneratorCircleCircle) {
  546.     int result = 0;
  547.  
  548.     CircleShape *circleA = &shapeA->circle;
  549.     CircleShape *circleB = &shapeB->circle;
  550.  
  551.     vec2 posA = transformA.translation;
  552.     vec2 posB = transformB.translation;
  553.  
  554.     // Get normal from distance between circles
  555.     vec2 distanceBetween = posB - posA;
  556.     vec2 normal;
  557.     if (glm::length2(distanceBetween) > 0) {
  558.         normal = glm::normalize(distanceBetween);
  559.     } else {
  560.         normal = vec2(1, 0);
  561.     }
  562.  
  563.     // Get distance and get closest point
  564.     float projDistance = glm::dot(distanceBetween, normal);
  565.     float bothRadius = circleA->radius + circleB->radius;
  566.     float d = -(bothRadius - projDistance);
  567.     vec2 pointOnA = posA + normal * circleA->radius;
  568.  
  569.     Contact *contact = &contacts[result++];
  570.     *contact = {};
  571.     contact->normal = normal;
  572.     contact->distance = d;
  573.     contact->pointOnA = pointOnA;
  574.     return(result);
  575. }
  576.  
  577. static CONTACT_GENERATOR(ContactGeneratorPlanePolygon) {
  578.     int result = 0;
  579.  
  580.     PlaneShape *plane = &shapeA->plane;
  581.     PolygonShape *poly = &shapeB->poly;
  582.  
  583.     vec2 posA = transformA.translation;
  584.     vec2 normalA = transformA.rotation[0];
  585.     mat2 rotAToB = glm::transpose(transformB.rotation);
  586.     vec2 normalB = rotAToB * normalA;
  587.  
  588.     vec2 pointsOnA[2];
  589.     float distanceToA[2];
  590.     int clipTypeOnB[2];
  591.     int numPoints = 0;
  592.  
  593.     Face faceB = GetFace(poly->numVerts, &poly->localVerts[0], -normalB);
  594.     vec2 supportPoint1 = faceB.points[0] * transformB;
  595.     vec2 planePoint = posA;
  596.     vec2 distanceToPlane = supportPoint1 - planePoint;
  597.     float d = glm::dot(distanceToPlane, normalA);
  598.     if (d > 0) {
  599.         pointsOnA[0] = supportPoint1 + normalA * -d;
  600.         distanceToA[0] = d;
  601.         numPoints = 1;
  602.         clipTypeOnB[0] = 0;
  603.     } else {
  604.         vec2 supportPoint2 = faceB.points[1] * transformB;
  605.         vec2 distance0 = supportPoint1 - planePoint;
  606.         float d0 = glm::dot(distance0, normalA);
  607.         if (d0 <= 0) {
  608.             int idx = numPoints++;
  609.             pointsOnA[idx] = supportPoint1 + normalA * -d0;
  610.             distanceToA[idx] = d0;
  611.             clipTypeOnB[idx] = 1;
  612.         }
  613.  
  614.         vec2 distance1 = supportPoint2 - planePoint;
  615.         float d1 = glm::dot(distance1, normalA);
  616.         if (d0 <= 0) {
  617.             int idx = numPoints++;
  618.             pointsOnA[idx] = supportPoint2 + normalA * -d1;
  619.             distanceToA[idx] = d1;
  620.             clipTypeOnB[idx] = 2;
  621.         }
  622.     }
  623.  
  624.     for (int pointIndex = 0; pointIndex < numPoints; pointIndex++) {
  625.         Contact *contact = &contacts[result++];
  626.         *contact = {};
  627.         contact->distance = distanceToA[pointIndex];
  628.         contact->normal = normalA;
  629.         contact->pointOnA = pointsOnA[pointIndex];
  630.     }
  631.  
  632.     return(result);
  633. }
  634.  
  635. static CONTACT_GENERATOR(ContactGeneratorPolygonPolygon) {
  636.     int result = 0;
  637.  
  638.     PolygonShape *polyA = &shapeA->poly;
  639.     PolygonShape *polyB = &shapeB->poly;
  640.  
  641.     vec2 posA = transformA.translation;
  642.  
  643.     // Get vertices for A and B
  644.     vec2 *localVertsA = polyA->localVerts;
  645.     vec2 *localVertsB = polyB->localVerts;
  646.     int numVertsA = polyA->numVerts;
  647.     int numVertsB = polyB->numVerts;
  648.  
  649.     // Query SAT for A -> B or B -> A
  650.     SATResult resultA = QuerySAT(transformA, transformB, numVertsA, localVertsA, numVertsB, localVertsB);
  651.     SATResult resultB = QuerySAT(transformB, transformA, numVertsB, localVertsB, numVertsA, localVertsA);
  652.  
  653.     // Create input manifold and give A more weight than B
  654.     const float kRelTol = 0.99f;
  655.     const float kAbsTol = 0.001f;
  656.     ManifoldInput input;
  657.     if (resultA.distance > kRelTol * resultB.distance + kAbsTol) {
  658.         input = MakeInputManifold(false, resultA.normal, transformA, transformB, numVertsA, localVertsA, numVertsB, localVertsB);
  659.     } else {
  660.         input = MakeInputManifold(true, resultB.normal, transformB, transformA, numVertsB, localVertsB, numVertsA, localVertsA);
  661.     }
  662.  
  663.     ManifoldOutput output = {};
  664.  
  665.     // Get face vertices for A and B
  666.     Face faceA = GetFace(input.numVertsA, input.localVertsA, input.localNormalA);
  667.     Face faceB = GetFace(input.numVertsB, input.localVertsB, -(input.rotAtoB * input.localNormalA));
  668.  
  669.     // Transform face vertices for A and B
  670.     vec2 sA1 = faceA.points[0] * input.transformA;
  671.     vec2 sA2 = faceA.points[1] * input.transformA;
  672.     vec2 sB1 = faceB.points[0] * input.transformB;
  673.     vec2 sB2 = faceB.points[1] * input.transformB;
  674.  
  675.     // Transform local normal A and set as final normal
  676.     output.normal = input.transformA.rotation * input.localNormalA;
  677.  
  678.     if (resultA.distance > 0 || resultB.distance > 0) {
  679.         // We are separated
  680.  
  681.         // Get closest points from B to A and from A to B
  682.         float regionA, regionB;
  683.         vec2 closestOnA = GetClosestPointOnLineSegment(sB1, sA1, sA2, &regionA);
  684.         vec2 closestOnB = GetClosestPointOnLineSegment(closestOnA, sB1, sB2, &regionB);
  685.  
  686.         // Get the separation distance
  687.         float distance = glm::dot(sB1 - closestOnA, output.normal);
  688.  
  689.         // Reconstruct output normal and distance based on distance for closest points
  690.         if ((regionA < 0 || regionA > 1) || (regionB < 0 || regionB > 1)) {
  691.             vec2 closestDistance = closestOnB - closestOnA;
  692.             output.normal = glm::normalize(closestDistance);
  693.             distance = glm::dot(closestDistance, output.normal);
  694.         }
  695.  
  696.         // Write out points and distances
  697.         int idx = output.count++;
  698.         output.distances[idx] = distance;
  699.         output.points[idx] = closestOnA;
  700.     } else {
  701.         // We are penetrating or touching
  702.  
  703.         // Clip face line segments (Incident front face against reference side planes)
  704.         //              Keep points only when behind the reference front face
  705.         //              Clip points are on B - need to project back to A
  706.         ClipResult clipPoints = Clip(output.normal, sA1, sA2, sB1, sB2);
  707.         vec2 clipDistance0 = clipPoints.points[0] - sA1;
  708.         float distance0 = glm::dot(clipDistance0, output.normal);
  709.         if (distance0 <= 0) {
  710.             int idx = output.count++;
  711.             output.points[idx] = clipPoints.points[0] + output.normal * -distance0;
  712.             output.distances[idx] = distance0;
  713.             output.features[idx] = 1;
  714.         }
  715.         vec2 clipDistance1 = clipPoints.points[1] - sA1;
  716.         float distance1 = glm::dot(clipDistance1, output.normal);
  717.         if (distance1 <= 0) {
  718.             int idx = output.count++;
  719.             output.points[idx] = clipPoints.points[1] + output.normal * -distance1;
  720.             output.distances[idx] = distance1;
  721.             output.features[idx] = 2;
  722.         }
  723.     }
  724.  
  725.     // Move points from A to B and invert normal (When B > A)
  726.     if (input.flip) {
  727.         for (int pointIndex = 0; pointIndex < output.count; pointIndex++) {
  728.             output.points[pointIndex] += output.normal * output.distances[pointIndex];
  729.         }
  730.         output.normal *= -1.0f;
  731.     }
  732.  
  733.     // Create final contact points
  734.     for (int i = 0; i < output.count; i++) {
  735.         Contact *contact = &contacts[result++];
  736.         *contact = {};
  737.         contact->distance = output.distances[i];
  738.         contact->normal = output.normal;
  739.         contact->pointOnA = output.points[i];
  740.     }
  741.  
  742.     return(result);
  743. }
  744. inline Transform MakeTransform(vec2 pos, float angle) {
  745.     Transform result;
  746.     result.translation = pos;
  747.     result.rotation = glm::orientate2(angle);
  748.     return(result);
  749. }
  750. static void ApplyImpulse(Body *body, const vec2 &impulse, const vec2 &point) {
  751.     body->velocity += impulse * body->invMass;
  752.     body->angularVelocity += Cross(point, impulse) * body->invInertia;
  753. }
  754. static void GameUpdate(float dt, World *world, InputState *input) {
  755.     // Update interaction
  756.     Body *newHotBody = 0;
  757.     for (int bodyIndex = 0; bodyIndex < world->numBodies; ++bodyIndex) {
  758.         Body *body = world->bodies + bodyIndex;
  759.         vec2 deltaPos = input->mouse.pos - body->position;
  760.         if (glm::length2(deltaPos) <= InteractionRadius * InteractionRadius) {
  761.             newHotBody = body;
  762.         }
  763.     }
  764.     world->interaction.hotBody = newHotBody;
  765.     if (IsDown(input->mouse.leftMouseButton)) {
  766.         if (world->interaction.hotBody && !world->interaction.activeBody) {
  767.             world->interaction.activeBody = world->interaction.hotBody;
  768.             world->interaction.type = InteractionType::InteractionType_MoveRotate;
  769.             world->interaction.dragging.startPos = input->mouse.pos;
  770.         }
  771.     } else {
  772.         if (world->interaction.type != InteractionType::InteractionType_None) {
  773.             world->interaction.activeBody = 0;
  774.             world->interaction.type = InteractionType::InteractionType_None;
  775.         }
  776.     }
  777.  
  778.     if (world->interaction.type != InteractionType::InteractionType_None) {
  779.         assert(world->interaction.activeBody);
  780.         switch (world->interaction.type) {
  781.         case InteractionType::InteractionType_MoveRotate:
  782.         {
  783.             vec2 deltaPos = input->mouse.pos - world->interaction.dragging.startPos;
  784. #if EDIT_MODE
  785.             world->interaction.activeBody->position += deltaPos;
  786. #else
  787.             world->interaction.activeBody->velocity += deltaPos * 10.0f;
  788. #endif
  789.             world->interaction.dragging.startPos = input->mouse.pos;
  790.             float rotAmount = Tau32 / 100.0f;
  791.             char buffer[255];
  792.             if (WasDown(input->keyboard.q)) {
  793.                 world->interaction.activeBody->rotation += rotAmount;
  794.                 sprintf_s(buffer, ArrayCount(buffer), "Rotation to right: %f\n", world->interaction.activeBody->rotation);
  795.                 OutputDebugString(buffer);
  796.             } else if (WasDown(input->keyboard.e)) {
  797.                 world->interaction.activeBody->rotation -= rotAmount;
  798.                 sprintf_s(buffer, ArrayCount(buffer), "Rotation to left: %f\n", world->interaction.activeBody->rotation);
  799.                 OutputDebugString(buffer);
  800.             }
  801.         }; break;
  802.         }
  803.     }
  804.  
  805. #if !EDIT_MODE
  806.     if (WasDown(input->keyboard.f1)) {
  807.         world->stepEnabled = !world->stepEnabled;
  808.         world->step = false;
  809.     } else if (WasDown(input->keyboard.space)) {
  810.         if (world->stepEnabled) {
  811.             world->step = true;
  812.         }
  813.     }
  814.  
  815.     // Exit out when single step enabled and no step is requested
  816.     if (world->stepEnabled) {
  817.         if (!world->step) return;
  818.         world->step = false;
  819.     }
  820.  
  821.     // Integrate acceleration
  822.     for (int bodyIndex = 0; bodyIndex < world->numBodies; ++bodyIndex) {
  823.         Body *body = world->bodies + bodyIndex;
  824.         if (body->type == BodyType::Dynamic) {
  825.             vec2 acceleration = world->gravity + (body->force * body->mass);
  826.             body->velocity += acceleration * dt;
  827.             body->angularVelocity += body->torque * body->invInertia;
  828.         }
  829.     }
  830. #endif
  831.  
  832.     // Create arbiters (Body pairs)
  833.     world->numArbiters = 0;
  834.     for (int bodyIndexA = 0; bodyIndexA < world->numBodies; ++bodyIndexA) {
  835.         Body *bodyA = world->bodies + bodyIndexA;
  836.         for (int bodyIndexB = bodyIndexA + 1; bodyIndexB < world->numBodies; ++bodyIndexB) {
  837.             Body *bodyB = world->bodies + bodyIndexB;
  838.             if ((bodyA->type == BodyType::Dynamic) || (bodyB->type == BodyType::Dynamic)) {
  839.                 assert(world->numArbiters < MaxArbiterCount);
  840.                 Arbiter *arbiter = &world->arbiters[world->numArbiters++];
  841.                 *arbiter = {};
  842.                 arbiter->bodyA = bodyA;
  843.                 arbiter->bodyB = bodyB;
  844.                 // TODO: Fixed friction for now
  845.                 arbiter->friction = 0.4f;
  846.             }
  847.         }
  848.     }
  849.  
  850.     // Create contacts
  851.     for (int arbiterIndex = 0; arbiterIndex < world->numArbiters; ++arbiterIndex) {
  852.         Arbiter *arbiter = world->arbiters + arbiterIndex;
  853.         Shape* shapeA = &arbiter->bodyA->shape;
  854.         Shape* shapeB = &arbiter->bodyB->shape;
  855.         Body *bodyA = arbiter->bodyA;
  856.         Body *bodyB = arbiter->bodyB;
  857.  
  858.         bool swapped = false;
  859.         if (shapeA->type > shapeB->type) {
  860.             shapeA = &arbiter->bodyB->shape;
  861.             shapeB = &arbiter->bodyA->shape;
  862.             bodyA = arbiter->bodyB;
  863.             bodyB = arbiter->bodyA;
  864.             swapped = true;
  865.         }
  866.  
  867.         // Build transform
  868.         Transform transformA = MakeTransform(bodyA->position, bodyA->rotation);
  869.         Transform transformB = MakeTransform(bodyB->position, bodyB->rotation);
  870.  
  871.         // TODO: Implement a jump table to find a proper contact generation function call
  872.         arbiter->numContacts = 0;
  873.         if (shapeA->type == ShapeType::ShapeType_Plane && shapeB->type == ShapeType::ShapeType_Circle) {
  874.             arbiter->numContacts = ContactGeneratorPlaneCircle(transformA, shapeA, transformB, shapeB, arbiter->contacts);
  875.         } else if (shapeA->type == ShapeType::ShapeType_Plane && shapeB->type == ShapeType::ShapeType_Polygon) {
  876.             arbiter->numContacts = ContactGeneratorPlanePolygon(transformA, shapeA, transformB, shapeB, arbiter->contacts);
  877.         } else if (shapeA->type == ShapeType::ShapeType_Circle && shapeB->type == ShapeType::ShapeType_Circle) {
  878.             arbiter->numContacts = ContactGeneratorCircleCircle(transformA, shapeA, transformB, shapeB, arbiter->contacts);
  879.         } else if (shapeA->type == ShapeType::ShapeType_Polygon && shapeB->type == ShapeType::ShapeType_Polygon) {
  880.             arbiter->numContacts = ContactGeneratorPolygonPolygon(transformA, shapeA, transformB, shapeB, arbiter->contacts);
  881.         }
  882.  
  883.         if (swapped) {
  884.             for (int contactIndex = 0; contactIndex < arbiter->numContacts; ++contactIndex) {
  885.                 Contact *contact = arbiter->contacts + contactIndex;
  886.                 // Move contact point to the other body
  887.                 contact->pointOnA = contact->pointOnA + contact->normal * contact->distance;
  888.                 // The normal must be flipped as well
  889.                 contact->normal *= -1.0f;
  890.             }
  891.         }
  892.  
  893.         // Initialize contacts
  894.         for (int contactIndex = 0; contactIndex < arbiter->numContacts; ++contactIndex) {
  895.             Contact *contact = arbiter->contacts + contactIndex;
  896.  
  897.             contact->accumulatedNormalImpulse = contact->accumulatedTangentImpulse = 0;
  898.  
  899.             // Get center of mass (World space)
  900.             vec2 centerOfMassA = bodyA->position + bodyA->centroid;
  901.             vec2 centerOfMassB = bodyB->position + bodyB->centroid;
  902.  
  903.             // Get contact points (World space)
  904.             vec2 contactPointOnA = contact->pointOnA;
  905.             vec2 contactPointOnB = contactPointOnA + contact->normal * contact->distance;
  906.  
  907.             // Get contact arms (Relative space)
  908.             contact->relativeArmA = contactPointOnA - centerOfMassA;
  909.             contact->relativeArmB = contactPointOnB - centerOfMassB;
  910.  
  911.             // Get normal rotation on the z-plane
  912.             float rnA = Cross(contact->relativeArmA, contact->normal);
  913.             float rnB = Cross(contact->relativeArmB, contact->normal);
  914.  
  915.             // Build normal mass ratio
  916.             float normalTensor = bodyA->invMass + bodyB->invMass + bodyA->invInertia * rnA * rnA + bodyB->invInertia * rnB * rnB;
  917.             contact->normalMassRatio = normalTensor > 0 ? 1.0f / normalTensor : 0;
  918.  
  919.             // Get tangent rotation in the z-plane
  920.             vec2 tangent = Cross(contact->normal, 1.0f);
  921.             float rtA = Cross(contact->relativeArmA, tangent);
  922.             float rtB = Cross(contact->relativeArmB, tangent);
  923.  
  924.             // Build tangent matrix
  925.             float tangentTensor = bodyA->invMass + bodyB->invMass + bodyA->invInertia * rtA * rtA + bodyB->invInertia * rtB * rtB;
  926.             contact->tangentMassRatio = tangentTensor > 0 ? 1.0f / tangentTensor : 0;
  927.         }
  928.     }
  929.  
  930. #if !EDIT_MODE
  931.     // Solve contacts
  932.     for (int iterationIndex = 0; iterationIndex < SolverIterationCount; ++iterationIndex) {
  933.         for (int arbiterIndex = 0; arbiterIndex < world->numArbiters; ++arbiterIndex) {
  934.             Arbiter *arbiter = world->arbiters + arbiterIndex;
  935.             Body *bodyA = arbiter->bodyA;
  936.             Body *bodyB = arbiter->bodyB;
  937.             for (int contactIndex = 0; contactIndex < arbiter->numContacts; ++contactIndex) {
  938.                 Contact *contact = arbiter->contacts + contactIndex;
  939.                 vec2 normal = contact->normal;
  940.  
  941.                 // Relative velocity on contact = vB + cross(wB, rB) - vA - cross(wA, rA);
  942.                 vec2 vAB = bodyB->velocity + Cross(bodyB->angularVelocity, contact->relativeArmB) - bodyA->velocity - Cross(bodyA->angularVelocity, contact->relativeArmA);
  943.  
  944.                 // Normal impulse
  945.                 float projNormalVel = glm::dot(vAB, normal);
  946.                 float remove = projNormalVel + contact->distance / dt;
  947.                 float normalImpulse = remove * contact->normalMassRatio;
  948.                 float newImpulse = glm::min(contact->accumulatedNormalImpulse + normalImpulse, 0.0f);
  949.                 float impulseChange = newImpulse - contact->accumulatedNormalImpulse;
  950.                 contact->accumulatedNormalImpulse = newImpulse;
  951.                 ApplyImpulse(bodyA, normal * impulseChange, contact->relativeArmA);
  952.                 ApplyImpulse(bodyB, -normal * impulseChange, contact->relativeArmB);
  953.  
  954.                 // Tangent impulse
  955.                 vec2 tangent = Cross(normal, 1.0f);
  956.                 float projTangentVel = glm::dot(vAB, tangent);
  957.                 float maxFriction = arbiter->friction * contact->accumulatedNormalImpulse;
  958.                 float tangentImpulse = projTangentVel * contact->tangentMassRatio;
  959.                 float newTangentImpulse = Clamp(maxFriction, contact->accumulatedTangentImpulse + tangentImpulse, -maxFriction);
  960.                 float tangentChange = newTangentImpulse - contact->accumulatedTangentImpulse;
  961.                 contact->accumulatedTangentImpulse = newTangentImpulse;
  962.                 ApplyImpulse(bodyA, tangent * tangentChange, contact->relativeArmA);
  963.                 ApplyImpulse(bodyB, -tangent * tangentChange, contact->relativeArmB);
  964.             }
  965.         }
  966.     }
  967.  
  968.     // Integrate velocity and clear forces
  969.     for (int bodyIndex = 0; bodyIndex < world->numBodies; ++bodyIndex) {
  970.         Body *body = world->bodies + bodyIndex;
  971.         if (body->type == BodyType::Dynamic) {
  972.             body->position += body->velocity * dt;
  973.             body->rotation += body->angularVelocity * dt;
  974.         }
  975.         body->force = vec2(0, 0);
  976.         body->torque = 0;
  977.     }
  978. #endif
  979.  
  980.     // Clear forces
  981.     for (int bodyIndex = 0; bodyIndex < world->numBodies; ++bodyIndex) {
  982.         Body *body = world->bodies + bodyIndex;
  983.         body->force = vec2(0, 0);
  984.         body->torque = 0;
  985.     }
  986. }
  987.  
  988. // -----------------------------------------
  989. // RENDERING
  990. // -----------------------------------------
  991.  
  992. static void DrawCircle(float radius, int numSegments = 32, bool filled = false) {
  993.     float segmentLength = Tau32 / numSegments;
  994.     glBegin(filled ? GL_POLYGON : GL_LINE_LOOP);
  995.     for (int segmentIndex = 0; segmentIndex < numSegments; ++segmentIndex) {
  996.         float angle = segmentIndex * segmentLength;
  997.         float xpos = glm::cos(angle) * radius;
  998.         float ypos = glm::sin(angle) * radius;
  999.         glVertex2f(xpos, ypos);
  1000.     }
  1001.     glEnd();
  1002. }
  1003. static void DrawRotationAxis() {
  1004.     float axisLen = 0.25f;
  1005.     glBegin(GL_LINES);
  1006.     glColor3f(0, 1, 0);
  1007.     glVertex2f(axisLen, 0);
  1008.     glVertex2f(0, 0);
  1009.     glColor3f(1, 0, 0);
  1010.     glVertex2f(0, axisLen);
  1011.     glVertex2f(0, 0);
  1012.     glEnd();
  1013. }
  1014. static void DrawPatternLine(vec2 start, vec2 end, float patternWidth = 0.05f) {
  1015.     vec2 line = end - start;
  1016.     float lineDistance = glm::length(start - end);
  1017.     vec2 normal = glm::normalize(line);
  1018.     int numParts = (int)(lineDistance / patternWidth);
  1019.     glBegin(GL_LINES);
  1020.     float d = patternWidth * 2;
  1021.     glVertex2f(start.x, start.y);
  1022.     glVertex2f(start.x + normal.x * patternWidth, start.y + normal.y * patternWidth);
  1023.     for (int i = 1; i < numParts / 2; ++i) {
  1024.         vec2 a = start + normal * d;
  1025.         vec2 b = a + normal * patternWidth;
  1026.         glVertex2f(a.x, a.y);
  1027.         glVertex2f(b.x, b.y);
  1028.         d += patternWidth * 2;
  1029.     }
  1030.     glVertex2f(end.x, end.y);
  1031.     glVertex2f(end.x - normal.x * patternWidth, end.y - normal.y * patternWidth);
  1032.     glEnd();
  1033. }
  1034.  
  1035. static void DrawBody(const mat4 &vp, Body *body) {
  1036.     Transform transform = MakeTransform(body->position, body->rotation);
  1037.     mat4 rot = mat4(transform.rotation);
  1038.     mat4 model = glm::translate(mat4(), vec3(transform.translation, 0)) * rot;
  1039.     mat4 mvp = vp * model;
  1040.  
  1041.     glLoadMatrixf(&mvp[0][0]);
  1042.     switch (body->shape.type) {
  1043.     case ShapeType::ShapeType_Plane:
  1044.     {
  1045.         PlaneShape *plane = &body->shape.plane;
  1046.         glColor3f(1, 1, 1);
  1047.         glBegin(GL_LINES);
  1048.         glVertex2f(0, plane->visualLength * 0.5f);
  1049.         glVertex2f(0, -plane->visualLength * 0.5f);
  1050.         glEnd();
  1051.     }; break;
  1052.  
  1053.     case ShapeType::ShapeType_Circle:
  1054.     {
  1055.         CircleShape *circle = &body->shape.circle;
  1056.         glColor3f(1, 1, 1);
  1057.         DrawCircle(circle->radius);
  1058.     }; break;
  1059.  
  1060.     case ShapeType::ShapeType_Polygon:
  1061.     {
  1062.         PolygonShape *poly = &body->shape.poly;
  1063.         glColor3f(1, 1, 1);
  1064.         glBegin(GL_LINE_LOOP);
  1065.         for (int vertexIndex = 0; vertexIndex < poly->numVerts; ++vertexIndex) {
  1066.             glVertex2f(poly->localVerts[vertexIndex].x, poly->localVerts[vertexIndex].y);
  1067.         }
  1068.         glEnd();
  1069.     }; break;
  1070.     }
  1071.  
  1072.     // Draw axis translated with mass centroid
  1073.     mat4 axisModel = glm::translate(mvp, vec3(body->centroid, 0));
  1074.     glLoadMatrixf(&axisModel[0][0]);
  1075.     DrawRotationAxis();
  1076. }
  1077. static void DrawContact(const mat4 &vp, Contact *contact) {
  1078.     mat4 contactModel = glm::translate(vp, vec3(contact->pointOnA, 0));
  1079.     glLoadMatrixf(&contactModel[0][0]);
  1080.     glColor3f(1, 0, 0);
  1081.     DrawCircle(0.05f, 16, true);
  1082.     glColor3f(1, 1, 0);
  1083.     DrawPatternLine(vec2(0, 0), vec2(0, 0) + contact->normal * contact->distance);
  1084.  
  1085.     vec2 pointOnB = contact->pointOnA + contact->normal * contact->distance;
  1086.     contactModel = glm::translate(vp, vec3(pointOnB, 0));
  1087.     glLoadMatrixf(&contactModel[0][0]);
  1088.     glColor3f(1, 0, 1);
  1089.     DrawCircle(0.05f, 16, true);
  1090. }
  1091. static void GameRender(World *world, RenderState *renderState, InputState *input) {
  1092.     mat4 proj = glm::ortho(-world->boundaryExt.x, world->boundaryExt.x, -world->boundaryExt.y, world->boundaryExt.y, 0.0f, 100.0f);
  1093.     mat4 view = glm::scale(glm::translate(mat4(), vec3(renderState->cameraOffset, 0)), vec3(renderState->cameraScale));
  1094.     mat4 vp = proj * view;
  1095.  
  1096.     glViewport(renderState->viewportOffset.x, renderState->viewportOffset.y, renderState->viewportSize.x, renderState->viewportSize.y);
  1097.     glMatrixMode(GL_MODELVIEW);
  1098.     glLoadMatrixf(&vp[0][0]);
  1099.  
  1100.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1101.  
  1102.     // Draw world boundaries
  1103.     glColor3f(0, 0, 1);
  1104.     glBegin(GL_LINE_LOOP);
  1105.     glVertex2f(world->boundaryExt.x, world->boundaryExt.y);
  1106.     glVertex2f(-world->boundaryExt.x, world->boundaryExt.y);
  1107.     glVertex2f(-world->boundaryExt.x, -world->boundaryExt.y);
  1108.     glVertex2f(world->boundaryExt.x, -world->boundaryExt.y);
  1109.     glEnd();
  1110.  
  1111.     for (int bodyIndex = 0; bodyIndex < world->numBodies; ++bodyIndex) {
  1112.         Body *body = world->bodies + bodyIndex;
  1113.         DrawBody(vp, body);
  1114.     }
  1115.  
  1116.     // Draw interaction body
  1117.     if (world->interaction.activeBody) {
  1118.         mat4 mvp = glm::translate(vp, vec3(world->interaction.activeBody->position, 0));
  1119.         glLoadMatrixf(&mvp[0][0]);
  1120.         glColor3f(1.0f, 0.0f, 0.0f);
  1121.         DrawCircle(InteractionRadius, 16);
  1122.     } else if (world->interaction.hotBody) {
  1123.         mat4 mvp = glm::translate(vp, vec3(world->interaction.hotBody->position, 0));
  1124.         glLoadMatrixf(&mvp[0][0]);
  1125.         glColor3f(0.0f, 1.0f, 0.0f);
  1126.         DrawCircle(InteractionRadius, 16);
  1127.     }
  1128.  
  1129.     // Draw contacts
  1130.     for (int arbiterIndex = 0; arbiterIndex < world->numArbiters; ++arbiterIndex) {
  1131.         Arbiter *arbiter = world->arbiters + arbiterIndex;
  1132.         for (int contactIndex = 0; contactIndex < arbiter->numContacts; ++contactIndex) {
  1133.             Contact *contact = arbiter->contacts + contactIndex;
  1134.             DrawContact(vp, contact);
  1135.         }
  1136.     }
  1137.  
  1138.     // Draw mouse pos
  1139.     mat4 mouseMat = glm::translate(vp, vec3(input->mouse.pos, 0));
  1140.     glLoadMatrixf(&mouseMat[0][0]);
  1141.     glColor3f(0.4f, 0.6f, 0.7f);
  1142.     DrawCircle(0.1f, 16);
  1143. }
  1144.  
  1145. // -----------------------------------------
  1146. // Win32 Platform
  1147. // -----------------------------------------
  1148.  
  1149. #define WIN32_CLASSNAME "PhysicsWin32"
  1150. #define DEFAULT_SCREEN_WIDTH 1280
  1151. #define DEFAULT_SCREEN_HEIGHT 720
  1152.  
  1153. // WGL definitions
  1154. #define PFNWGLSWAPINTERVALPROC(name) BOOL name(int value)
  1155. typedef PFNWGLSWAPINTERVALPROC(wgl_swap_interval);
  1156.  
  1157. // Internal variables
  1158. static bool globalRunning;
  1159. static uint64_t globalPerfCounterFrequency;
  1160. static wgl_swap_interval *wglSwapIntervalEXT;
  1161.  
  1162. inline LARGE_INTEGER Win32GetWallClock() {
  1163.     LARGE_INTEGER result;
  1164.     QueryPerformanceCounter(&result);
  1165.     return(result);
  1166. }
  1167. inline float Win32GetSecondsElapsed(LARGE_INTEGER start, LARGE_INTEGER end) {
  1168.     float result = (float)(end.QuadPart - start.QuadPart) / (float)globalPerfCounterFrequency;
  1169.     return(result);
  1170. }
  1171.  
  1172. LRESULT CALLBACK Win32MessageProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  1173.     switch (msg) {
  1174.     case WM_DESTROY:
  1175.     case WM_CLOSE:
  1176.         globalRunning = 0;
  1177.         break;
  1178.     default:
  1179.         return DefWindowProc(hwnd, msg, wParam, lParam);
  1180.     }
  1181.     return 0;
  1182. }
  1183. static bool Win32SetPixelFormat(HDC deviceContext) {
  1184.     // Define pixel format
  1185.     PIXELFORMATDESCRIPTOR pfd = {};
  1186.     pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  1187.     pfd.nVersion = 1;
  1188.     pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
  1189.     pfd.iPixelType = PFD_TYPE_RGBA;
  1190.     pfd.cColorBits = 32;
  1191.     pfd.cDepthBits = 24;
  1192.     pfd.cAlphaBits = 8;
  1193.     pfd.iLayerType = PFD_MAIN_PLANE;
  1194.  
  1195.     // Find pixel format
  1196.     int nPixelFormat = ChoosePixelFormat(deviceContext, &pfd);
  1197.     if (nPixelFormat == 0) {
  1198.         return false;
  1199.     }
  1200.  
  1201.     // Set pixel format
  1202.     if (!SetPixelFormat(deviceContext, nPixelFormat, &pfd)) {
  1203.         return false;
  1204.     }
  1205.  
  1206.     return true;
  1207. }
  1208. static void Win32LoadWGLExtensions(HINSTANCE instance) {
  1209.     // Create a dummy window and context to load extensions
  1210.     WNDCLASSA windowClass = {};
  1211.     windowClass.lpfnWndProc = DefWindowProcA;
  1212.     windowClass.hInstance = instance;
  1213.     windowClass.lpszClassName = "PhysicsWGLLoader";
  1214.     if (RegisterClassA(&windowClass)) {
  1215.         HWND window = CreateWindowExA(0, windowClass.lpszClassName, "Physics WGL Loader", 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, windowClass.hInstance, 0);
  1216.         HDC WindowDC = GetDC(window);
  1217.         if (Win32SetPixelFormat(WindowDC)) {
  1218.             HGLRC OpenGLRC = wglCreateContext(WindowDC);
  1219.             if (wglMakeCurrent(WindowDC, OpenGLRC)) {
  1220.                 wglSwapIntervalEXT = (wgl_swap_interval *)wglGetProcAddress("wglSwapIntervalEXT");
  1221.                 wglMakeCurrent(0, 0);
  1222.             }
  1223.             wglDeleteContext(OpenGLRC);
  1224.         }
  1225.         ReleaseDC(window, WindowDC);
  1226.         DestroyWindow(window);
  1227.         UnregisterClassA(windowClass.lpszClassName, instance);
  1228.     }
  1229. }
  1230. static bool Win32CreateOpenGL(HINSTANCE instance, HDC deviceContext, HGLRC *renderingContext) {
  1231.     // Load opengl extensions
  1232.     Win32LoadWGLExtensions(instance);
  1233.  
  1234.     // Set pixel format so we can use opengl in our window
  1235.     if (!Win32SetPixelFormat(deviceContext)) {
  1236.         return false;
  1237.     }
  1238.  
  1239.     // Create a opengl rendering context
  1240.     HGLRC rc = wglCreateContext(deviceContext);
  1241.     if (!rc) {
  1242.         return false;
  1243.     }
  1244.  
  1245.     // Activate the opengl rendering context
  1246.     if (!wglMakeCurrent(deviceContext, rc)) {
  1247.         wglDeleteContext(rc);
  1248.         return false;
  1249.     }
  1250.  
  1251.     // Enable vsync if possible
  1252.     if (wglSwapIntervalEXT) {
  1253.         wglSwapIntervalEXT(1);
  1254.     }
  1255.  
  1256.     *renderingContext = rc;
  1257.  
  1258.     return 1;
  1259. }
  1260. static void Win32DestroyOpenGL(HGLRC *renderingContext) {
  1261.     if (renderingContext) {
  1262.         // Disable opengl rendering context
  1263.         wglMakeCurrent(NULL, NULL);
  1264.         // Delete opengl rendering context
  1265.         wglDeleteContext(*renderingContext);
  1266.         *renderingContext = 0;
  1267.     }
  1268. }
  1269. static void Win32ProcessKeyboardMessage(ButtonState *newState, B32 isDown) {
  1270.     if (newState->endedDown != isDown) {
  1271.         newState->endedDown = isDown;
  1272.         ++newState->halfTransitionCount;
  1273.     }
  1274. }
  1275. static void Win32ProcessMessages(KeyboardState *keyboardState) {
  1276.     MSG msg;
  1277.     while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
  1278.         switch (msg.message) {
  1279.         case WM_QUIT:
  1280.         case WM_CLOSE:
  1281.         {
  1282.             globalRunning = false;
  1283.         }; break;
  1284.         case WM_SYSKEYDOWN:
  1285.         case WM_SYSKEYUP:
  1286.         case WM_KEYDOWN:
  1287.         case WM_KEYUP:
  1288.         {
  1289.             uint64_t keyCode = msg.wParam;
  1290.             B32 altKeyWasDown = (msg.lParam & (1 << 29));
  1291.             B32 wasDown = ((msg.lParam & (1 << 30)) != 0);
  1292.             B32 isDown = ((msg.lParam & (1 << 31)) == 0);
  1293.             if (wasDown != isDown) {
  1294.                 switch (keyCode) {
  1295.                 case VK_SPACE:
  1296.                     Win32ProcessKeyboardMessage(&keyboardState->space, isDown);
  1297.                     break;
  1298.                 case VK_F1:
  1299.                     Win32ProcessKeyboardMessage(&keyboardState->f1, isDown);
  1300.                     break;
  1301.                 case (int)'Q':
  1302.                     Win32ProcessKeyboardMessage(&keyboardState->q, isDown);
  1303.                     break;
  1304.                 case (int)'E':
  1305.                     Win32ProcessKeyboardMessage(&keyboardState->e, isDown);
  1306.                     break;
  1307.                 }
  1308.  
  1309.                 if (isDown) {
  1310.                     if (keyCode == VK_F4 && altKeyWasDown) {
  1311.                         globalRunning = false;
  1312.                     }
  1313.                     if (keyCode == VK_RETURN && altKeyWasDown) {
  1314.                         if (msg.hwnd) {
  1315.                             // TODO: Toggle fullscreen on Return+Alt
  1316.                         }
  1317.                     }
  1318.                 }
  1319.             }
  1320.         }; break;
  1321.         default:
  1322.         {
  1323.             TranslateMessage(&msg);
  1324.             DispatchMessage(&msg);
  1325.         }; break;
  1326.         }
  1327.     }
  1328. }
  1329.  
  1330. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow) {
  1331.     // Get performance counter frequency
  1332.     LARGE_INTEGER perfCounterFreqResult;
  1333.     QueryPerformanceFrequency(&perfCounterFreqResult);
  1334.     globalPerfCounterFrequency = perfCounterFreqResult.QuadPart;
  1335.  
  1336.     // Register window class
  1337.     WNDCLASSEX wcex = {};
  1338.     wcex.cbSize = sizeof(WNDCLASSEX);
  1339.     wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  1340.     wcex.lpfnWndProc = Win32MessageProc;
  1341.     wcex.hInstance = hInstance;
  1342.     wcex.lpszClassName = WIN32_CLASSNAME;
  1343.     wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  1344.     wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  1345.     wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  1346.     if (!RegisterClassEx(&wcex)) {
  1347.         return -1;
  1348.     }
  1349.  
  1350.     // Create window
  1351.     HWND windowHandle = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, WIN32_CLASSNAME, "Physics Win32", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, DEFAULT_SCREEN_WIDTH, DEFAULT_SCREEN_HEIGHT, NULL, NULL, hInstance, NULL);
  1352.     if (windowHandle == NULL) {
  1353.         return -1;
  1354.     }
  1355.  
  1356.     // Get device context
  1357.     HDC deviceContext = GetDC(windowHandle);
  1358.     if (!deviceContext) {
  1359.         return -1;
  1360.     }
  1361.  
  1362.     // Create and initialize opengl
  1363.     HGLRC renderingContext = 0;
  1364.     if (!Win32CreateOpenGL(hInstance, deviceContext, &renderingContext)) {
  1365.         return -1;
  1366.     }
  1367.  
  1368.     // Get monitor refresh rate in hz
  1369.     int monitorRefreshHz = 60;
  1370.     int refreshRate = GetDeviceCaps(deviceContext, VREFRESH);
  1371.     if (refreshRate > 1) {
  1372.         monitorRefreshHz = refreshRate;
  1373.     }
  1374.     float gameUpdateHz = (float)monitorRefreshHz;
  1375.     float targetSecondsPerFrame = 1.0f / gameUpdateHz;
  1376.  
  1377.     // Initialize states
  1378.     RenderState renderState = {};
  1379.     renderState.cameraScale = 0.75f;
  1380.     renderState.cameraOffset = vec2(0, 0);
  1381.  
  1382.     World world = {};
  1383.     GameInit(&world);
  1384.  
  1385.     InputState input[2] = {};
  1386.     InputState *newInput = &input[0];
  1387.     InputState *oldInput = &input[1];
  1388.  
  1389.     ShowWindow(windowHandle, nCmdShow);
  1390.     UpdateWindow(windowHandle);
  1391.  
  1392.     // Initialize timing infos
  1393.     LARGE_INTEGER lastCounter = Win32GetWallClock();
  1394.  
  1395.     globalRunning = true;
  1396.     while (globalRunning) {
  1397.         // Preserve keyboard states from previous frame
  1398.         KeyboardState *oldKeyboardState = &oldInput->keyboard;
  1399.         KeyboardState *newKeyboardState = &newInput->keyboard;
  1400.         *newKeyboardState = {};
  1401.         for (int buttonIndex = 0; buttonIndex < KeyboardButton_Count; ++buttonIndex) {
  1402.             newKeyboardState->buttons[buttonIndex].endedDown = newKeyboardState->buttons[buttonIndex].endedDown;
  1403.         }
  1404.  
  1405.         // Process messages
  1406.         Win32ProcessMessages(newKeyboardState);
  1407.  
  1408.         // Update viewport for current window size
  1409.         {
  1410.             RECT windowSize;
  1411.             GetClientRect(windowHandle, &windowSize);
  1412.             renderState.gameSize = vec2(world.boundaryExt.x * 2, world.boundaryExt.y * 2);
  1413.             renderState.screenSize.x = (windowSize.right - windowSize.left) + 1;
  1414.             renderState.screenSize.y = (windowSize.bottom - windowSize.top) + 1;
  1415.             renderState.renderScale = (float)renderState.screenSize.x / renderState.gameSize.x;
  1416.             renderState.viewportOffset = ivec2(0, 0);
  1417.             renderState.viewportSize.x = renderState.screenSize.x;
  1418.             renderState.viewportSize.y = (int)(renderState.screenSize.x / GameAspect);
  1419.             if (renderState.viewportSize.y > renderState.screenSize.y) {
  1420.                 renderState.viewportSize.y = renderState.screenSize.y;
  1421.                 renderState.viewportSize.x = (int)(renderState.viewportSize.y * GameAspect);
  1422.                 renderState.renderScale = (float)renderState.viewportSize.x / renderState.gameSize.x;
  1423.             }
  1424.             renderState.viewportOffset.x = (renderState.screenSize.x - renderState.viewportSize.x) / 2;
  1425.             renderState.viewportOffset.y = (renderState.screenSize.y - renderState.viewportSize.y) / 2;
  1426.         }
  1427.  
  1428.         // Mouse movement and buttons
  1429.         {
  1430.             POINT mousePos;
  1431.             GetCursorPos(&mousePos);
  1432.             ScreenToClient(windowHandle, &mousePos);
  1433.             int mouseX = mousePos.x;
  1434.             int mouseY = (renderState.screenSize.y - 1) - mousePos.y;
  1435.             newInput->mouse.pos = Unproject(&renderState, mouseX, mouseY);
  1436.             DWORD WinButtonID[MouseButton_Count] =
  1437.             {
  1438.                 VK_LBUTTON,
  1439.                 VK_MBUTTON,
  1440.                 VK_RBUTTON,
  1441.                 VK_XBUTTON1,
  1442.                 VK_XBUTTON2,
  1443.             };
  1444.             for (int buttonIndex = 0; buttonIndex < MouseButton_Count; ++buttonIndex) {
  1445.                 newInput->mouse.buttons[buttonIndex] = oldInput->mouse.buttons[buttonIndex];
  1446.                 newInput->mouse.buttons[buttonIndex].halfTransitionCount = 0;
  1447.                 Win32ProcessKeyboardMessage(&newInput->mouse.buttons[buttonIndex], GetKeyState(WinButtonID[buttonIndex]) & (1 << 15));
  1448.             }
  1449.         }
  1450.  
  1451.         // Update and render
  1452.         GameUpdate(targetSecondsPerFrame, &world, newInput);
  1453.         GameRender(&world, &renderState, newInput);
  1454.  
  1455.         // Present frame
  1456.         SwapBuffers(deviceContext);
  1457.  
  1458.         // Update timing infos
  1459.         LARGE_INTEGER endCounter = Win32GetWallClock();
  1460.         float secondsPerFrame = Win32GetSecondsElapsed(lastCounter, endCounter);
  1461.         lastCounter = endCounter;
  1462.  
  1463.         // Swap game input for next frame
  1464.         SwapPtr(InputState, newInput, oldInput);
  1465.     }
  1466.  
  1467.     // Destroy all opengl stuff
  1468.     Win32DestroyOpenGL(&renderingContext);
  1469.  
  1470.     // Destroy the window
  1471.     ReleaseDC(windowHandle, deviceContext);
  1472.     DestroyWindow(windowHandle);
  1473.     UnregisterClass(wcex.lpszClassName, wcex.hInstance);
  1474.  
  1475.     return 0;
  1476. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement