Przeglądaj źródła

Start heightmap

Miloslav Ciz 3 lat temu
rodzic
commit
1a2cc040bc
3 zmienionych plików z 252 dodań i 3 usunięć
  1. 5 3
      programs/car.c
  2. 94 0
      programs/heightmap.c
  3. 153 0
      tinyphysicsengine.h

+ 5 - 3
programs/car.c

@@ -8,7 +8,9 @@
 #include "carModel.h"
 #include "carModel.h"
 
 
 #define ACCELERATION 35
 #define ACCELERATION 35
-#define TURN_RATE 400
+#define TURN_RATE 300
+#define TURN_FRICTION 300
+#define FORW_FRICTION 32
 
 
 TPE_Unit rampPoits[6] =
 TPE_Unit rampPoits[6] =
 {
 {
@@ -135,7 +137,7 @@ wheelSize = TPE_JOINT_SIZE(carBody->joints[0]) + 30;
 TPE_bodyMoveBy(carBody,TPE_vec3(3000,1000,0));
 TPE_bodyMoveBy(carBody,TPE_vec3(3000,1000,0));
 
 
 carBody->elasticity = 64; 
 carBody->elasticity = 64; 
-carBody->friction = 32;//64; 
+carBody->friction = FORW_FRICTION;//64; 
 
 
   while (helper_running)
   while (helper_running)
   {
   {
@@ -298,7 +300,7 @@ else
   ja = carSide;
   ja = carSide;
 
 
 TPE_Vec3 diff =
 TPE_Vec3 diff =
-TPE_vec3Times(ja,  (TPE_vec3Dot(ja,jv) * 2) / 3     );
+TPE_vec3Times(ja,  (TPE_vec3Dot(ja,jv) * TURN_FRICTION) / TPE_FRACTIONS_PER_UNIT     );
 
 
 
 
 jv = TPE_vec3Minus(jv,diff);
 jv = TPE_vec3Minus(jv,diff);

+ 94 - 0
programs/heightmap.c

@@ -0,0 +1,94 @@
+#define CAMERA_STEP 200
+
+#include "helper.h"
+
+#define GRID_SIZE 3000
+
+TPE_Unit height(int32_t x, int32_t y)
+{
+  //return x * 20;
+  //return 2000 + 100 * x + y;
+
+  return _TPE_hash(x / 3 + y) % 8000;
+}
+
+TPE_Vec3 environmentDistance(TPE_Vec3 p, TPE_Unit maxD)
+{
+/*
+#define XX 1
+#define YY 0
+#define XX2 0
+#define YY2 1
+return TPE_envLineSegment(p,
+    TPE_vec3(XX * 4000,height(XX,YY),YY * 4000),
+    TPE_vec3(XX2 * 4000,height(XX2,YY2),YY2 * 4000));
+*/
+  return TPE_envHeightmap(p,TPE_vec3(0,0,0),GRID_SIZE,height,maxD);
+
+//return TPE_envHalfPlane(p,TPE_vec3(0,0,0),TPE_vec3(2,-512,0));
+}
+
+int main(void)
+{
+
+
+
+  helper_init();
+
+  helper_debugDrawOn = 1;
+
+  tpe_world.environmentFunction = environmentDistance;
+
+  s3l_scene.camera.transform.translation.z = -3000;
+  s3l_scene.camera.transform.translation.y = 2000;
+  s3l_scene.camera.transform.translation.x = 0;
+  s3l_scene.camera.transform.rotation.y = TPE_FRACTIONS_PER_UNIT / 16;
+
+  while (helper_running)
+  {
+    helper_frameStart();
+
+    helper_cameraFreeMovement();
+
+if (helper_frame % 32 == 0)
+{
+helper_printCamera();
+
+  printf("cam square: %d %d\n",
+    s3l_scene.camera.transform.translation.x / GRID_SIZE -
+    (s3l_scene.camera.transform.translation.x < 0),
+    s3l_scene.camera.transform.translation.z / GRID_SIZE -
+    (s3l_scene.camera.transform.translation.z < 0));
+}
+
+    if (helper_debugDrawOn)
+      helper_debugDraw(1);
+
+TPE_Vec3 ppp =
+  TPE_envHeightmap(
+TPE_vec3(
+s3l_scene.camera.transform.translation.x,
+s3l_scene.camera.transform.translation.y,
+s3l_scene.camera.transform.translation.z
+)
+,TPE_vec3(0,0,0),GRID_SIZE,height,50000);
+    
+helper_drawPoint3D(ppp,0,255,0);
+
+
+
+for (int yy = -5; yy <= 5; ++yy)
+  for (int xx = -5; xx <= 5; ++xx)
+  {
+    TPE_Vec3 aaa = TPE_vec3(xx * GRID_SIZE,height(xx,yy),yy * GRID_SIZE);
+    helper_drawPoint3D(aaa,255,0,0);
+
+  } 
+
+    helper_frameEnd();
+  }
+
+  helper_end();
+
+  return 0;
+}

+ 153 - 0
tinyphysicsengine.h

@@ -190,6 +190,7 @@ typedef struct
 
 
 static inline TPE_Unit TPE_abs(TPE_Unit x);
 static inline TPE_Unit TPE_abs(TPE_Unit x);
 static inline TPE_Unit TPE_max(TPE_Unit a, TPE_Unit b);
 static inline TPE_Unit TPE_max(TPE_Unit a, TPE_Unit b);
+static inline TPE_Unit TPE_min(TPE_Unit a, TPE_Unit b);
 
 
 /** Function used for defining static environment, working similarly to an SDF
 /** Function used for defining static environment, working similarly to an SDF
   (signed distance function). The parameters are: 3D point P, max distance D.
   (signed distance function). The parameters are: 3D point P, max distance D.
@@ -449,6 +450,11 @@ TPE_Vec3 TPE_envInfiniteCylinder(TPE_Vec3 point, TPE_Vec3 center, TPE_Vec3
 TPE_Vec3 TPE_envCylinder(TPE_Vec3 point, TPE_Vec3 center, TPE_Vec3 direction,
 TPE_Vec3 TPE_envCylinder(TPE_Vec3 point, TPE_Vec3 center, TPE_Vec3 direction,
   TPE_Unit radius);
   TPE_Unit radius);
 
 
+TPE_Vec3 TPE_envLineSegment(TPE_Vec3 point, TPE_Vec3 a, TPE_Vec3 b);
+
+TPE_Vec3 TPE_envHeightmap(TPE_Vec3 point, TPE_Vec3 center, TPE_Unit gridSize,
+  TPE_Unit (*heightFunction)(int32_t x, int32_t y), TPE_Unit maxDist);
+
 /** Environment function for triagnular prism, e.g. for ramps. The sides array
 /** Environment function for triagnular prism, e.g. for ramps. The sides array
   contains three 2D coordinates of points of the triangle in given plane with
   contains three 2D coordinates of points of the triangle in given plane with
   respect to the center. WARNING: the points must be specified in counter
   respect to the center. WARNING: the points must be specified in counter
@@ -2760,6 +2766,11 @@ TPE_Unit TPE_max(TPE_Unit a, TPE_Unit b)
   return (a > b) ? a : b;
   return (a > b) ? a : b;
 }
 }
 
 
+TPE_Unit TPE_min(TPE_Unit a, TPE_Unit b)
+{
+  return (a < b) ? a : b;
+}
+
 TPE_Vec3 TPE_envAATriPrism(TPE_Vec3 point, TPE_Vec3 center,
 TPE_Vec3 TPE_envAATriPrism(TPE_Vec3 point, TPE_Vec3 center,
   const TPE_Unit sides[6], TPE_Unit depth, uint8_t direction)
   const TPE_Unit sides[6], TPE_Unit depth, uint8_t direction)
 {
 {
@@ -3001,4 +3012,146 @@ uint8_t TPE_testClosestPointFunction(TPE_ClosestPointFunction f,
   return 1;
   return 1;
 }
 }
 
 
+TPE_Vec3 TPE_envLineSegment(TPE_Vec3 point, TPE_Vec3 a, TPE_Vec3 b)
+{
+  point = TPE_vec3Minus(point,a);
+
+  b = TPE_vec3Minus(b,a);
+
+  point = TPE_vec3Project(point,b);
+
+  if (TPE_vec3Dot(point,b) < 0)
+    point = TPE_vec3(0,0,0);
+  else if (TPE_abs(point.x) + TPE_abs(point.y) + TPE_abs(point.z) >
+    TPE_abs(b.x) + TPE_abs(b.y) + TPE_abs(b.z))
+    point = b;
+
+  point = TPE_vec3Plus(point,a);
+
+  return point;
+}
+
+TPE_Vec3 TPE_envHeightmap(TPE_Vec3 point, TPE_Vec3 center, TPE_Unit gridSize,
+  TPE_Unit (*heightFunction)(int32_t x, int32_t y), TPE_Unit maxDist)
+{
+  point = TPE_vec3Minus(point,center);
+
+  TPE_Vec3 closestP = TPE_vec3(TPE_INFINITY,TPE_INFINITY,TPE_INFINITY);
+  TPE_Unit closestD = TPE_INFINITY;
+
+  int16_t startSquareX = point.x / gridSize - (point.x < 0),
+          startSquareY = point.z / gridSize - (point.z < 0);
+
+  int16_t squareX = startSquareX,
+          squareY = startSquareY;
+
+  uint8_t spiralDir = 1;
+  uint16_t spiralStep = 1, spiralStepsLeft = 1;
+
+  TPE_Vec3 // 4 corners of the current square
+    bl = TPE_vec3(squareX * gridSize,heightFunction(squareX,squareY),squareY * gridSize),
+    br = TPE_vec3(bl.x + gridSize,heightFunction(squareX + 1,squareY),bl.z),
+    tl = TPE_vec3(bl.x,heightFunction(squareX,squareY + 1),bl.z + gridSize),
+    tr = TPE_vec3(br.x,heightFunction(squareX + 1,squareY + 1),tl.z);
+
+  for (uint16_t i = 0; i < 1024; ++i) // while (1) should work in theory but...
+  {
+    if ((TPE_min(TPE_abs(squareX - startSquareX),
+      TPE_abs(squareY - startSquareY)) - 1) * gridSize
+      > TPE_min(maxDist,closestD))
+      break; // here we can no longer find the dist we're looking for => end
+
+    for (uint8_t j = 0; j < 2; ++j) // check the two triangles of the segment
+    {
+      TPE_Vec3 testP = TPE_envHalfPlane(point,j == 0 ? bl : tr,
+        TPE_vec3Normalized(j == 0 ?
+          TPE_vec3Cross(TPE_vec3Minus(tl,bl),TPE_vec3Minus(br,bl)) :
+          TPE_vec3Cross(TPE_vec3Minus(br,tr),TPE_vec3Minus(tl,tr))));
+
+      TPE_Unit testD = TPE_DISTANCE(testP,point);
+
+      if (testD < closestD)
+      {
+        if (j == 0 ? // point is inside the triangle?
+          (testP.x >= bl.x && testP.z >= bl.z && (testP.x - bl.x <= tl.z - testP.z)) :
+          (testP.x <= tr.x && testP.z <= tr.z && (testP.x - bl.x >= tl.z - testP.z)))
+        {
+          closestP = testP;
+          closestD = testD;
+        }
+        else
+        {
+          // point outside the triangle, check individual boundary sides
+#define testEdge(a,b) \
+  testP = TPE_envLineSegment(point,a,b); testD = TPE_DISTANCE(testP,point); \
+  if (testD < closestD) { closestP = testP; closestD = testD; }
+
+          testEdge(j == 0 ? bl : tr,br)
+          testEdge(j == 0 ? bl : tr,tl)
+          testEdge(br,tl)
+
+#undef testEdge
+        }
+      }
+    }
+
+    // now step to another square, in spiralling way:
+
+    switch (spiralDir)
+    {
+      case 0: // moving up
+        squareY++; 
+
+        bl = tl; br = tr;
+        tl = TPE_vec3(tl.x,heightFunction(squareX,squareY + 1),tl.z + gridSize);
+        tr = TPE_vec3(tr.x,heightFunction(squareX + 1,squareY + 1),tl.z + gridSize);
+
+        break;
+
+      case 1: // moving right
+        squareX++;
+
+        bl = br; tl = tr;
+        tr = TPE_vec3(tr.x + gridSize,heightFunction(squareX + 1,squareY + 1),tr.z);
+        br = TPE_vec3(br.x + gridSize,heightFunction(squareX + 1,squareY),br.z);
+
+        break;
+
+      case 2: // moving down
+        squareY--;
+
+        tl = bl; tr = br;
+        bl = TPE_vec3(bl.x,heightFunction(squareX,squareY),bl.z - gridSize);
+        br = TPE_vec3(br.x,heightFunction(squareX + 1,squareY),br.z - gridSize);
+
+        break;
+
+      case 3: // moving left
+        squareX--;
+
+        br = bl; tr = tl;
+        tl = TPE_vec3(tl.x - gridSize,heightFunction(squareX,squareY + 1),tl.z);
+        bl = TPE_vec3(bl.x - gridSize,heightFunction(squareX,squareY),bl.z);
+
+        break;
+
+      default: break;
+    }
+
+    spiralStepsLeft--;
+
+    if (spiralStepsLeft == 0)
+    {
+      spiralDir = spiralDir != 0 ? spiralDir - 1 : 3;
+
+      if (spiralDir == 3 || spiralDir == 1)
+        spiralStep++;
+
+      spiralStepsLeft = spiralStep;
+    }
+  }
+
+  return TPE_vec3Plus(closestP,center);
+}
+
 #endif // guard
 #endif // guard