logo.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. #pragma once
  2. #include <gl2d/gl2d.h>
  3. #include <imgui.h>
  4. #include <baseContainer.h>
  5. #include <shortcutApi/shortcutApi.h>
  6. #include <pikaSizes.h>
  7. #include <imgui_spinner.h>
  8. #include <ph2d/ph2d.h>
  9. #include <unordered_set>
  10. #include <sstream>
  11. struct Logo: public Container
  12. {
  13. // Function to generate a pastel color based on an input number
  14. glm::vec3 generatePastelColor(int inputNumber)
  15. {
  16. srand(inputNumber);
  17. // Seed random number generator based on input
  18. //auto baseColor = glm::vec3(0,0,0);
  19. //glm::vec3 baseColor = glm::ballRand<float>(1.0f); // Random direction on a sphere
  20. glm::vec3 baseColor(rand() % 100 / 100.f, rand() % 100 / 100.f, rand() % 100 / 100.f);
  21. baseColor = glm::abs(baseColor); // Ensure positive values
  22. // Adjust saturation to pastel range by mixing with white
  23. float pastelFactor = 0.7f;
  24. glm::vec3 pastelColor = glm::mix(baseColor, glm::vec3(1.0f), pastelFactor);
  25. // Map input number into [0,1] range
  26. float modifier = (inputNumber % 1000) / 1000.0f;
  27. pastelColor += modifier * 0.1f;
  28. return glm::clamp(pastelColor, 0.0f, 1.0f);
  29. }
  30. gl2d::Renderer2D renderer;
  31. ph2d::PhysicsEngine physicsEngine;
  32. gl2d::Texture ballTexture;
  33. gl2d::Texture logoTexture;
  34. std::unordered_set<unsigned int> ropeIds;
  35. std::unordered_map<unsigned int, glm::vec3> colors;
  36. //static constexpr float floorPos = 850;
  37. static constexpr float floorPos = 1000;
  38. bool simulate = 1;
  39. //todo user can request imgui ids; shortcut manager context; allocators
  40. static ContainerStaticInfo containerInfo()
  41. {
  42. ContainerStaticInfo info = {};
  43. info.defaultHeapMemorySize = pika::MB(20);
  44. info.requestImguiFbo = true;
  45. info.pushAnImguiIdForMe = true;
  46. info.andInputWithWindowHasFocus = 0;
  47. info.andInputWithWindowHasFocusLastFrame = 0;
  48. return info;
  49. }
  50. bool create(RequestedContainerInfo &requestedInfo, pika::StaticString<256> commandLineArgument)
  51. {
  52. renderer.create(requestedInfo.requestedFBO.fbo);
  53. ballTexture = pika::gl2d::loadTexture(PIKA_RESOURCES_PATH "ball.png", requestedInfo);
  54. logoTexture = pika::gl2d::loadTexture(PIKA_RESOURCES_PATH "logo2.png", requestedInfo);
  55. physicsEngine.simulationphysicsSettings.gravity = glm::vec2(0, 9.81) * 1.f;
  56. //physicsEngine.simulationphysicsSettings.gravity = glm::vec2(0, 0);
  57. physicsEngine.simulationphysicsSettings.airDragCoeficient = 0.01f;
  58. physicsEngine.collisionChecksCount = 2;
  59. physicsEngine.setFixedTimeStamp = 0;
  60. auto file = requestedInfo.readEntireFileBinaryAsAString(PIKA_RESOURCES_PATH "physicsOrder.txt");
  61. std::stringstream stream(file);
  62. {
  63. unsigned int id = 0;
  64. float r, g, b;
  65. while (stream.good() && !stream.eof() && stream >> id)
  66. {
  67. stream >> r >> g >> b;
  68. colors[id] = glm::vec3{r,g,b} / 255.f;
  69. };
  70. }
  71. //physicsEngine.addBody({500, 200}, ph2d::createConvexPolygonCollider(shape, 5));
  72. //physicsEngine.addBody({500, 1100},
  73. // ph2d::createBoxCollider({1100, 10}));
  74. //physicsEngine.addBody({1, 800}, ph2d::createBoxCollider({300, 250}));
  75. //auto body = physicsEngine.addBody({500, 500}, ph2d::createBoxCollider({400, 50}));
  76. //physicsEngine.bodies[body].flags.setFreezePosition();
  77. //physicsEngine.bodies[body].flags.setFreezeRotation();
  78. //physicsEngine.bodies[1].motionState.mass = 0;
  79. //physicsEngine.bodies[1].motionState.momentOfInertia = 0;
  80. //physicsEngine.addBody({700, 700}, ph2d::createBoxCollider({300, 300}));
  81. //physicsEngine.addBody({600, 600}, ph2d::createBoxCollider({350, 350}));
  82. //physicsEngine.bodies[1].motionState.rotation = glm::radians(30.f);
  83. //physicsEngine.addBody({900, 500}, ph2d::createCircleCollider({40}));
  84. //physicsEngine.addBody({550, 700}, ph2d::createCircleCollider({25}));
  85. //physicsEngine.addBody({600, 600}, ph2d::createBoxCollider({50, 50}));
  86. //std::cout << ph2d::vectorToRotation({0,1}) << "\n";
  87. //std::cout << ph2d::vectorToRotation({-1,1}) << "\n";
  88. //std::cout << ph2d::vectorToRotation({-1,0}) << "\n";
  89. //std::cout << ph2d::vectorToRotation({0,-1}) << "\n";
  90. //std::cout << ph2d::vectorToRotation({1,0}) << "\n";
  91. //
  92. //std::cout << "\n";
  93. //std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({0,1}) ).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({0,1}) ).y << "\n";
  94. //std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({-1,1})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({-1,1})).y << "\n";
  95. //std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({-1,0})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({-1,0})).y << "\n";
  96. //std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({0,-1})).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({0,-1})).y << "\n";
  97. //std::cout << ph2d::rotationToVector(ph2d::vectorToRotation({1,0}) ).x << " " << ph2d::rotationToVector(ph2d::vectorToRotation({1,0}) ).y << "\n";
  98. //auto b = physicsEngine.addHalfSpaceStaticObject({0, floorPos + 10}, {0.0, 1});
  99. //physicsEngine.bodies[b].staticFriction = 0;
  100. //physicsEngine.bodies[b].dynamicFriction = 0;
  101. //physicsEngine.addBody({500, floorPos}, ph2d::createBoxCollider({900, 50}));
  102. //physicsEngine.bodies.back().motionState.mass = 0;
  103. //physicsEngine.bodies.back().motionState.momentOfInertia = 0;
  104. return true;
  105. }
  106. bool update(pika::Input input, pika::WindowState windowState,
  107. RequestedContainerInfo &requestedInfo)
  108. {
  109. #pragma region init stuff
  110. int w = 0; int h = 0;
  111. w = windowState.frameBufferW; //window w
  112. h = windowState.frameBufferH; //window h
  113. glClearColor(0.2, 0.22, 0.23, 1);
  114. glClear(GL_COLOR_BUFFER_BIT); //clear screen
  115. renderer.updateWindowMetrics(w, h);
  116. #pragma endregion
  117. //ph2d::AABB box1 = glm::vec4{300,300, 300,300};
  118. //
  119. //ph2d::AABB box2 = glm::vec4(glm::vec2(platform::getRelMousePosition()) - glm::vec2(50, 50), 100, 100);
  120. //
  121. //renderer.renderRectangleOutline(box1.asVec4(), Colors_White);
  122. //
  123. //auto color = Colors_White;
  124. //
  125. //if (ph2d::AABBvsAABB(box1, box2))
  126. //{
  127. // color = Colors_Red;
  128. //}
  129. //
  130. //renderer.renderRectangleOutline(box2.asVec4(), color);
  131. //ph2d::Circle a = glm::vec3{450,450, 150};
  132. //ph2d::Circle b = glm::vec3(glm::vec2(platform::getRelMousePosition()), 50);
  133. //renderer.renderCircleOutline(a.center, a.r, Colors_White, 2, 32);
  134. //
  135. //auto color = Colors_White;
  136. //if (ph2d::CirclevsCircle(a, b))
  137. //{
  138. // color = Colors_Red;
  139. //}
  140. //renderer.renderCircleOutline(b.center, b.r, color, 2, 32);
  141. static int simulationSpeed = 1;
  142. float rightPos = 1000;
  143. //physicsEngine.bodies[0].motionState.rotation = glm::radians(-30.f);
  144. ImGui::PushStyleColor(ImGuiCol_WindowBg, {0.3,0.3,0.3,0.8});
  145. ImGui::Begin("Settings");
  146. ImGui::DragInt("Speed", &simulationSpeed);
  147. //physicsEngine.bodies[0].motionState.angularVelocity = 1.5;
  148. ImGui::Text("Mouse pos %d, %d", input.mouseX, input.mouseY);
  149. ImGui::Checkbox("Simulate", &simulate);
  150. ImGui::End();
  151. ImGui::PopStyleColor();
  152. static int selected = -1;
  153. //mouse
  154. //if (!simulate && input.rMouse.held())
  155. //{
  156. // physicsEngine.bodies[1].motionState.setPos({input.mouseX, input.mouseY});
  157. //}
  158. static glm::vec2 pressedPosition = {};
  159. if (input.lMouse.pressed())
  160. {
  161. selected = -1;
  162. for (auto b : physicsEngine.bodies)
  163. {
  164. if (b.second.intersectPoint({input.mouseX, input.mouseY}))
  165. {
  166. selected = b.first;
  167. pressedPosition = {input.mouseX, input.mouseY};
  168. }
  169. }
  170. }
  171. if (selected > 0)
  172. {
  173. renderer.renderLine(pressedPosition, {input.mouseX, input.mouseY}, Colors_Blue, 4);
  174. }
  175. if (input.lMouse.released() && selected > 0)
  176. {
  177. glm::vec2 force = pressedPosition - glm::vec2({input.mouseX, input.mouseY});
  178. //physicsEngine.bodies[selected].motionState.velocity += force;
  179. force *= physicsEngine.bodies[selected].motionState.mass;
  180. force *= 4.f;
  181. physicsEngine.bodies[selected].applyImpulseWorldPosition(force,
  182. //physicsEngine.bodies[selected].motionState.pos
  183. pressedPosition
  184. );
  185. //physicsEngine.bodies[selected].motionState.angularVelocity = 10;
  186. selected = -1;
  187. pressedPosition = {};
  188. }
  189. for (int i = 0; i < simulationSpeed; i++)
  190. {
  191. //gravity
  192. //if(simulate)
  193. //for (int i=0; i<physicsEngine.bodies.size(); i++)
  194. //{
  195. // if(physicsEngine.bodies[i].motionState.mass != 0 && physicsEngine.bodies[i].motionState.mass != INFINITY)
  196. // physicsEngine.bodies[i].motionState.acceleration += glm::vec2(0, 9.81) * 100.f;
  197. //}
  198. if (simulate)
  199. {
  200. physicsEngine.collisionChecksCount = 1;
  201. physicsEngine.runSimulation(0.008);
  202. }
  203. else
  204. {
  205. physicsEngine.collisionChecksCount = 0;
  206. //physicsEngine.runSimulation(0.008);
  207. }
  208. for (auto &it : physicsEngine.bodies)
  209. {
  210. auto &b = it.second;
  211. auto bottom = b.getAABB().max().y;
  212. auto left = b.getAABB().min().x;
  213. auto right = b.getAABB().max().x;
  214. auto top = b.getAABB().min().y;
  215. if (bottom > floorPos)
  216. {
  217. float diff = bottom - floorPos;
  218. b.motionState.pos.y -= diff;
  219. b.motionState.lastPos = b.motionState.pos;
  220. b.motionState.velocity.y *= -0.9f;
  221. }
  222. if (left < 0)
  223. {
  224. b.motionState.pos.x -= left;
  225. b.motionState.lastPos = b.motionState.pos;
  226. b.motionState.velocity.x *= -0.9;
  227. }
  228. if (right > rightPos)
  229. {
  230. b.motionState.pos.x -= right - rightPos;
  231. b.motionState.lastPos = b.motionState.pos;
  232. b.motionState.velocity.x *= -0.9;
  233. }
  234. if (top < 0)
  235. {
  236. b.motionState.pos.y -= top;
  237. b.motionState.lastPos = b.motionState.pos;
  238. b.motionState.velocity.y *= -0.9;
  239. }
  240. }
  241. }
  242. //std::cout << physicsEngine.bodies[0].getAABB().max().x << "\n";
  243. //renderer.renderRectangleOutline({300 - 25, 100 - 25, 50, 50}, Colors_Red);
  244. //renderer.renderRectangleOutline({600 - 25, 200 - 25, 50, 50}, Colors_Red);
  245. //auto a = physicsEngine.bodies[0].getAABB();
  246. //auto b = physicsEngine.bodies[1].getAABB();
  247. //ph2d::Circle a1 = glm::vec3{a.center(),a.size.x / 2};
  248. //ph2d::Circle b1 = glm::vec3{b.center(),b.size.x / 2};
  249. //if (ph2d::CirclevsCircle(a1, b1, p, n, contactPoint))
  250. //{
  251. // penetrated = true;
  252. //}
  253. //auto a = physicsEngine.bodies[0].getAABB();
  254. //auto b = physicsEngine.bodies[1];
  255. //ph2d::LineEquation lineEquation;
  256. //lineEquation.createFromRotationAndPoint(b.motionState.rotation,
  257. // b.motionState.pos);
  258. //if (ph2d::HalfSpaceVSCircle(lineEquation, a, p, n, contactPoint))
  259. //{
  260. // penetrated = true;
  261. //}
  262. //glm::vec2 cornersA[4] = {};
  263. //glm::vec2 cornersB[4] = {};
  264. //physicsEngine.bodies[0].getAABB().getCornersRotated(cornersA, physicsEngine.bodies[0].motionState.rotation);
  265. //physicsEngine.bodies[1].getAABB().getCornersRotated(cornersB, physicsEngine.bodies[1].motionState.rotation);
  266. //
  267. //float rez = ph2d::calculatePenetrationAlongOneAxe(cornersA, 4, cornersB, 4, {1,0});
  268. //if (rez > 0)
  269. //{
  270. // penetrated = true;
  271. //}
  272. ImGui::Begin("Settings");
  273. int count = physicsEngine.bodies.size();
  274. ImGui::Text("Count: %d", count);
  275. if (ImGui::Button("Make Photo"))
  276. {
  277. glm::ivec2 size = {};
  278. auto pixels = logoTexture.readTextureData(0, &size);
  279. auto samplePixel = [&](glm::vec2 uv)
  280. {
  281. uv = glm::clamp(uv, {0,0}, {1,1});
  282. uv.y = 1 - uv.y;
  283. uv *= glm::vec2(size.x-1, size.y-1);
  284. uv = glm::ivec2(uv);
  285. glm::vec4 rez = {};
  286. rez.r = pixels[(4 * (uv.x + uv.y * size.x)) + 0];
  287. rez.g = pixels[(4 * (uv.x + uv.y * size.x)) + 1];
  288. rez.b = pixels[(4 * (uv.x + uv.y * size.x)) + 2];
  289. rez.a = pixels[(4 * (uv.x + uv.y * size.x)) + 3];
  290. return rez;
  291. };
  292. pika::memory::pushCustomAllocatorsToStandard();
  293. {
  294. std::ofstream f(PIKA_RESOURCES_PATH "physicsOrder.txt");
  295. for (auto &o : physicsEngine.bodies)
  296. {
  297. f << o.first << " ";
  298. glm::vec2 uv = o.second.motionState.pos;
  299. uv /= glm::vec2(rightPos, floorPos);
  300. auto color = samplePixel(uv);
  301. f << color.r << ' ' << color.g << ' ' << color.b << "\n";
  302. }
  303. f.close();
  304. }
  305. pika::memory::popCustomAllocatorsToStandard();
  306. }
  307. ImGui::End();
  308. static bool start = 0;
  309. if (input.buttons[pika::Button::P].held())
  310. {
  311. start = true;
  312. }
  313. if (start)
  314. {
  315. static int ballsCounter = 0;
  316. static float timer = 0;
  317. static float counter = 0;
  318. if (ballsCounter < 600)
  319. {
  320. if (timer <= 0)
  321. {
  322. auto p = physicsEngine.addBody({rightPos/2, floorPos/2}, ph2d::createCircleCollider({24}));
  323. glm::vec2 direction = {sin(counter), cos(counter)};
  324. //direction.y = std::abs(direction.y);
  325. //direction.y += 0.1;
  326. direction = glm::normalize(direction);
  327. physicsEngine.bodies[p].motionState.velocity = direction * 2000.f;
  328. timer = 0.05;
  329. ballsCounter++;
  330. };
  331. timer -= 0.008;
  332. counter += 0.008 * 2.f;
  333. };
  334. }
  335. for (auto &i : physicsEngine.bodies)
  336. {
  337. auto &b = i.second;
  338. auto color = glm::vec4(generatePastelColor(i.first), 1);
  339. if (i.first == selected)
  340. {
  341. color = Colors_Blue;
  342. }
  343. //if (b.intersectPoint({input.mouseX, input.mouseY}))
  344. //{
  345. // color = Colors_Turqoise;
  346. //}
  347. color = glm::vec4(colors[i.first], 1);
  348. //if (penetrated)
  349. //{
  350. // color = Colors_Red;
  351. //}
  352. //if (OBBvsPoint(physicsEngine.bodies[i].getAABB(),
  353. // physicsEngine.bodies[i].motionState.rotation,
  354. // {input.mouseX, input.mouseY}))
  355. //{
  356. // color = Colors_Blue;
  357. //}
  358. if (b.collider.type == ph2d::ColliderCircle)
  359. {
  360. renderer.renderCircleOutline(b.motionState.pos,
  361. b.collider.collider.circle.radius, color, 2, 32);
  362. glm::vec2 vector = {1,0};
  363. vector = ph2d::rotateAroundCenter(vector, b.motionState.rotation);
  364. renderer.renderLine(b.motionState.pos, b.motionState.pos + vector *
  365. b.collider.collider.circle.radius, color, 4);
  366. renderer.renderRectangle(b.getAABB().asVec4(), ballTexture, color, {}, b.motionState.rotation);
  367. }
  368. else if (b.collider.type == ph2d::ColliderBox)
  369. {
  370. float rotation = glm::degrees(b.motionState.rotation);
  371. renderer.renderRectangleOutline(b.getAABB().asVec4(), color, 2, {}, rotation);
  372. }
  373. else if (b.collider.type == ph2d::ColliderHalfSpace)
  374. {
  375. ph2d::LineEquation lineEquation;
  376. lineEquation.createFromRotationAndPoint(b.motionState.rotation,
  377. b.motionState.pos);
  378. glm::vec2 lineEquationStart = lineEquation.getClosestPointToOrigin();
  379. lineEquationStart -= lineEquation.getLineVector() * 1000.f;
  380. renderer.renderLine(lineEquationStart, lineEquationStart + lineEquation.getLineVector() * 2000.f, Colors_Red, 4);
  381. }
  382. else if (b.collider.type == ph2d::ColliderConvexPolygon)
  383. {
  384. auto &c = b.collider.collider.convexPolygon;
  385. for (int i = 0; i < c.vertexCount; i++)
  386. {
  387. glm::vec2 p1 = c.vertexesObjectSpace[i] + b.motionState.pos;
  388. glm::vec2 p2 = c.vertexesObjectSpace[(i + 1) % c.vertexCount] + b.motionState.pos;
  389. p1 = ph2d::rotateAroundPoint(p1, b.motionState.pos, b.motionState.rotation);
  390. p2 = ph2d::rotateAroundPoint(p2, b.motionState.pos, b.motionState.rotation);
  391. renderer.renderLine(p1, p2, color, 4);
  392. }
  393. }
  394. }
  395. //renderer.renderRectangle({-100, floorPos, 100000, 20});
  396. renderer.renderRectangle({
  397. glm::vec2(input.mouseX,input.mouseY) - glm::vec2(4,4), 8, 8}, Colors_Red);
  398. //glm::vec2 lineEquationStart = lineEquation.getClosestPointToOrigin();
  399. //lineEquationStart -= lineEquation.getLineVector() * 1000.f;
  400. //renderer.renderLine(lineEquationStart, lineEquationStart + lineEquation.getLineVector() * 2000.f, Colors_Red);
  401. //ph2d::LineEquation lineEquation;
  402. //lineEquation.createFromNormalAndPoint({0,1}, {0, floorPos});
  403. //float pl = 0;
  404. //pl = lineEquation.computeEquation(platform::getRelMousePosition());
  405. //ImGui::Begin("Settings");
  406. //ImGui::Text("Penetration line: %f", pl);
  407. //ImGui::End();
  408. //glm::vec2 p2 = platform::getRelMousePosition();
  409. //p2 = ph2d::rotateAroundCenter(p2, glm::radians(45.f));
  410. //renderer.renderRectangle({p2, 10, 10}, Colors_Red);
  411. renderer.flush();
  412. return true;
  413. }
  414. //optional
  415. void destruct(RequestedContainerInfo &requestedInfo)
  416. {
  417. }
  418. };