Advertisement
Guest User

Untitled

a guest
Jun 12th, 2019
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.74 KB | None | 0 0
  1. #include "task2.h"
  2.  
  3. int flattenIndex(int x, int y, int size_x) {
  4. // This is a utility function that maps a 2D index into a 1D index
  5. // for our flat vector structures (normals, positions, masses...)
  6. return x + y * size_x;
  7. }
  8.  
  9. void calcNormals(std::vector<float3>& normals,
  10. const std::vector<float3>& positions, int grid_x, int grid_y) {
  11. // TODO: calculate the normal for each particle vertex
  12. //
  13. // To compute the particle normal consider the particles connected via
  14. // structural springs. Use flattenIndex(int x, int y, int size_x) to convert
  15. // from 2D coordinates to a 1D index for vectors normals and positions.
  16. //
  17. // Parameters:
  18. // normals: resulting normals
  19. // positions: particle positions
  20. // grid_x, grid_y: particle-grid dimensions
  21.  
  22.  
  23. for(int y = 0; y < grid_y; y++)
  24. {
  25. for(int x = 0; x < grid_x; x++)
  26. {
  27. float3 curr_index = positions.at(flattenIndex(x,y,grid_x));
  28. float3 right_down = {0.0f,0.0f,0.0f};
  29. float3 left_down = {0.0f,0.0f,0.0f};
  30. float3 right_up = {0.0f,0.0f,0.0f};
  31. float3 left_up = {0.0f,0.0f,0.0f};
  32. // float3 temp_feder = {0.0f, 0.0f, 0.0f};
  33. //float3 temp_feder2 = {0.0f, 0.0f, 0.0f};
  34.  
  35.  
  36. if(x - 1 >= 0 && y + 1 < grid_y)
  37. {
  38. float3 temp_feder = positions.at(flattenIndex(x,y+1,grid_x)) - curr_index;
  39. float3 temp_feder2 = positions.at(flattenIndex(x-1,y,grid_x)) - curr_index;
  40. left_down = normalize(cross(temp_feder,temp_feder2));
  41.  
  42. }
  43. if(x - 1 >= 0 && y - 1 >= 0)
  44. {
  45. float3 temp_feder = positions.at(flattenIndex(x-1,y,grid_x)) - curr_index;
  46. float3 temp_feder2 = positions.at(flattenIndex(x,y - 1,grid_x)) - curr_index;
  47. left_up = normalize(cross(temp_feder,temp_feder2));
  48.  
  49. }
  50. if(x + 1 < grid_x && y -1 >= 0)
  51. {
  52. float3 temp_feder = positions.at(flattenIndex(x,y-1,grid_x)) - curr_index;
  53. float3 temp_feder2 = positions.at(flattenIndex(x+1,y,grid_x)) - curr_index;
  54. right_up = normalize(cross(temp_feder,temp_feder2));
  55.  
  56. }
  57. if(x + 1 < grid_x && y + 1 < grid_y)
  58. {
  59. float3 temp_feder = positions.at(flattenIndex(x + 1,y,grid_x)) - curr_index;
  60. float3 temp_feder2 = positions.at(flattenIndex(x,y + 1,grid_x)) - curr_index;
  61. right_down = normalize(cross(temp_feder,temp_feder2));
  62.  
  63. }
  64.  
  65.  
  66. int index = flattenIndex(x, y, grid_x);
  67. normals.at(index) = normalize(left_down + left_up + right_up + right_down);
  68.  
  69.  
  70.  
  71.  
  72.  
  73. }
  74. }
  75.  
  76. }
  77.  
  78. float3 calcWindAcc(const float3& normal, const float3& wind_force,
  79. float inv_mass) {
  80. // TODO: calculate the particle-dependent acceleration due to wind
  81. //
  82. // The wind strength should depend on the cosine (dot product) between the
  83. // particle normal and the wind direction (note that the wind can hit the
  84. // particle from the front or back). The resulting particle acceleration
  85. // caused by the wind is the above scaling times the inverse mass of the
  86. // particle times the wind force.
  87. //
  88. // Parameters:
  89. // normal: particle normal
  90. // wind_force: wind force in XYZ direction
  91. // inv_mass: inverse mass of the particle
  92. if(wind_force.x != 0.0f && wind_force.y != 0.0f && wind_force.z != 0.0f)
  93. {
  94. float3 wind_force_normal = normalize(wind_force);
  95. float save = std::fabs(dot(normal, wind_force_normal));
  96. float3 acc = inv_mass * wind_force * save;
  97. return acc;
  98. }
  99.  
  100.  
  101.  
  102.  
  103. return float3(0.f, 0.f, 0.f);
  104. }
  105.  
  106. void verletIntegration(std::vector<float3>& p_next,
  107. const std::vector<float3>& p_cur,
  108. const std::vector<float3>& p_prev,
  109. const std::vector<float3>& normals,
  110. const std::vector<float>& inv_masses, float damp,
  111. const float3& gravity, const float3& wind_force,
  112. float dt) {
  113. // TODO: for each particle perform the numerical integration
  114. //
  115. // Use the formula given in the assignment sheet to perform the Verlet
  116. // Integration. Do NOT add spring forces, as they are taken care of by the
  117. // fixup-step! Make sure that fixed particles (inverse mass = 0) do not change
  118. // their position! Bonus: The particle-dependent accelerations should also
  119. // consider the wind direction and strength => Use your implementation of
  120. // calcWindAcc()
  121. //
  122. // Parameters:
  123. // p_next: updated particle positions
  124. // p_cur: current paricle positions
  125. // p_prev: previous particle positions
  126. // normals: particle normals
  127. // inv_masses: inverse particle masses
  128. // damp: damping factor
  129. // gravity: gravity vector
  130. // wind_force: wind force
  131. // dt: timestep
  132. for(int itr = 0; itr < p_next.size(); itr++)
  133. p_next[itr] = inv_masses[itr] == 0.0f ? p_cur[itr] : (1 + damp) * p_cur[itr] - damp * p_prev[itr] +
  134. (gravity + calcWindAcc(normals[itr],wind_force,inv_masses[itr])) * powf(dt,2.0f);
  135.  
  136.  
  137.  
  138. }
  139.  
  140. void fixupStep(std::vector<float3>& p_out, const std::vector<float3>& p_in,
  141. int grid_x, int grid_y, float cloth_x, float cloth_y,
  142. const std::vector<float>& inv_masses, float fixup_percent,
  143. const std::vector<Sphere>& obstacles,
  144. bool apply_structural_fixup, bool apply_shear_fixup,
  145. bool apply_flexion_fixup) {
  146. // TODO: implement the fixup-step
  147. //
  148. // For each particle iterate over all particles connected via springs and
  149. // compute the movement required to restore each spring into its resting
  150. // position. Based on the mass ratio between the particle pairs compute the
  151. // part of the movement that would have to be carried out by the current
  152. // particle. Sum these movements up and update the particle position with a
  153. // fraction of that movement(fixup_percent of the full movement). Iterate over
  154. // all obstacles and resolve the collisions.
  155. //
  156. // *Only* apply the relevant fixup (structural/shear/flexion) if the
  157. // corresponding flag is set (apply_*_fixup)!
  158. //
  159. // Parameters:
  160. // p_out: new particle positions
  161. // p_in: current particle positions
  162. // grid_x, grid_y: particle-grid dimensions
  163. // cloth_x, cloth_y: cloth size
  164. // inv_masses: inverse particle masses
  165. // fix_percent: fixup percent [0..1]
  166. // obstacles: obstacle vector
  167. // apply_structural_fixup: only structural fixup if this is true
  168. // apply_shear_fixup: only apply shear fixup if this is true
  169. // apply_flexion_fixup: only apply flexion fixup if this is true
  170. float flex_x = (cloth_x/(grid_x - 1.0f)) * 2.0f;
  171. float flex_y = (cloth_y/(grid_y - 1.0f)) * 2.0f;
  172. float shear = std::sqrt(std::pow(cloth_x/(grid_x - 1.0f), 2) + std::pow(cloth_y/(grid_y - 1.0f), 2));
  173.  
  174.  
  175.  
  176. for(int y = 0; y < grid_y; y++)
  177. {
  178. for(int x = 0; x < grid_x; x++)
  179. {
  180. p_out.at(flattenIndex(x,y,grid_x)) = p_in.at(flattenIndex(x,y,grid_x));
  181. float offset = 0.0f;
  182. float distance = 0.0f;
  183. float mass = 0.0f;
  184.  
  185.  
  186. if(inv_masses.at(flattenIndex(x,y,grid_x)) > 0.0f)
  187. {
  188. /////////apply shear fixup /////////////////////////////
  189. ///////////////////////////////////////////////////////
  190. ///////////////////////////////////////////////////////
  191.  
  192.  
  193. if(apply_shear_fixup)
  194. {
  195. ///reset variables
  196. float3 feder = {0.0f,0.0f,0.0f};
  197. float3 particle1 = {0.0f,0.0f,0.0f};
  198. float3 particle2 = {0.0f,0.0f,0.0f};
  199. float3 particle3 = {0.0f,0.0f,0.0f};
  200. float3 particle4 = {0.0f,0.0f,0.0f};
  201. float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  202. if(x > 0 && y > 0)
  203. {
  204. feder = p_in.at(flattenIndex(x - 1, y - 1, grid_x));
  205. mass = inv_masses.at(flattenIndex(x - 1, y - 1, grid_x));
  206. // float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  207. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  208. offset = distance - shear;
  209. float mass_end = (beginning_mass / (mass + beginning_mass));
  210.  
  211.  
  212. particle1 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  213.  
  214. }
  215. //////////
  216. if(x < grid_x - 1 && y < grid_y - 1)
  217. {
  218. feder = p_in.at(flattenIndex(x + 1, y + 1, grid_x));
  219. mass = inv_masses.at(flattenIndex(x + 1, y + 1, grid_x));
  220. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  221. offset = distance - shear;
  222. float mass_end = (beginning_mass / (mass + beginning_mass));
  223. particle2 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  224.  
  225. }
  226. if(x > 0 && y < grid_y - 1)
  227. {
  228. feder = p_in.at(flattenIndex(x - 1, y + 1, grid_x));
  229. mass = inv_masses.at(flattenIndex(x - 1, y + 1, grid_x));
  230. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  231. offset = distance - shear;
  232. float mass_end = (beginning_mass / (mass + beginning_mass));
  233. particle3 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  234.  
  235. }
  236. if(x < grid_x - 1 && y > 0)
  237. {
  238. feder = p_in.at(flattenIndex(x + 1, y - 1, grid_x));
  239. mass = inv_masses.at(flattenIndex(x + 1, y - 1, grid_x));
  240. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  241. offset = distance - shear;
  242. float mass_end = (beginning_mass / (mass + beginning_mass));
  243. particle4 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  244.  
  245. }
  246. p_out.at(flattenIndex(x,y,grid_x)) = p_out.at(flattenIndex(x,y,grid_x)) + ((particle1 + particle2 + particle3 + particle4)*fixup_percent);
  247.  
  248. }
  249. ////////////////////////////////////////////////////////////////////////
  250.  
  251. ///apply flexion fixup ////////////////////////////////
  252. //////////////////////////////////////////////////////////////////////
  253.  
  254. if(apply_flexion_fixup)
  255. {
  256. ////reset variables
  257. float3 feder = {0.0f,0.0f,0.0f};
  258. float3 particle1 = {0.0f,0.0f,0.0f};
  259. float3 particle2 = {0.0f,0.0f,0.0f};
  260. float3 particle3 = {0.0f,0.0f,0.0f};
  261. float3 particle4 = {0.0f,0.0f,0.0f};
  262.  
  263. // offset = distance - shear;
  264. float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  265. if( x - 1 > 0 && x > 0)
  266. {
  267. feder = p_in.at(flattenIndex(x - 2, y, grid_x));
  268. mass = inv_masses.at(flattenIndex(x - 2, y, grid_x));
  269. // float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  270. distance =length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  271. offset = distance - flex_x;
  272. float mass_end = (beginning_mass / (mass + beginning_mass));
  273.  
  274.  
  275. particle1 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  276.  
  277. }
  278.  
  279. if(x < grid_x - 1 && x + 1 < grid_x - 1)
  280. {
  281. feder = p_in.at(flattenIndex(x + 2, y, grid_x));
  282. mass = inv_masses.at(flattenIndex(x + 2, y, grid_x));
  283. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  284. offset = distance - flex_x;
  285. float mass_end = (beginning_mass / (mass + beginning_mass));
  286.  
  287. particle2 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  288.  
  289. }
  290. if(y + 1 < grid_y - 1 && y < grid_y - 1)
  291. {
  292. feder = p_in.at(flattenIndex(x, y + 2, grid_x));
  293. mass = inv_masses.at(flattenIndex(x, y + 2, grid_x));
  294. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  295. offset = distance - flex_y;
  296. float mass_end = (beginning_mass / (mass + beginning_mass));
  297. particle3 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  298.  
  299. }
  300. if(y - 1 > 0 && y > 0)
  301. {
  302. feder = p_in.at(flattenIndex(x, y - 2, grid_x));
  303. mass = inv_masses.at(flattenIndex(x , y - 2, grid_x));
  304. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  305. offset = distance - flex_y;
  306. float mass_end = (beginning_mass / (mass + beginning_mass));
  307. particle4 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  308.  
  309. }
  310. p_out.at(flattenIndex(x,y,grid_x)) = p_out.at(flattenIndex(x,y,grid_x)) + ((particle1 + particle2 + particle3 + particle4)*fixup_percent);
  311.  
  312. }
  313.  
  314. //////////////////////////////////////////////////////////////////////////////
  315. //////////apply structural fixup /////////////////////////////////////////////
  316. /////////////////////////////////////////////////////////////////////////////
  317.  
  318. if(apply_structural_fixup)
  319. {
  320. ////reset variables
  321. float3 feder = {0.0f,0.0f,0.0f};
  322. float3 particle1 = {0.0f,0.0f,0.0f};
  323. float3 particle2 = {0.0f,0.0f,0.0f};
  324. float3 particle3 = {0.0f,0.0f,0.0f};
  325. float3 particle4 = {0.0f,0.0f,0.0f};
  326. // offset = distance - shear;
  327. float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  328. if(y < grid_y - 1)
  329. {
  330. feder = p_in.at(flattenIndex(x, y + 1, grid_x));
  331. mass = inv_masses.at(flattenIndex(x, y + 1, grid_x));
  332. // float beginning_mass = inv_masses.at(flattenIndex(x,y,grid_x));
  333. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  334. offset = distance - (cloth_y/(grid_y - 1.0f));
  335. float mass_end = (beginning_mass / (mass + beginning_mass));
  336.  
  337.  
  338. particle1 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  339.  
  340. }
  341.  
  342. if(x < grid_x - 1)
  343. {
  344. feder = p_in.at(flattenIndex(x + 1, y, grid_x));
  345. mass = inv_masses.at(flattenIndex(x + 1, y, grid_x));
  346. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  347. offset = distance - (cloth_x/(grid_x - 1.0f));
  348. float mass_end = (beginning_mass / (mass + beginning_mass));
  349. particle2 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  350.  
  351. }
  352. if(x > 0)
  353. {
  354. feder = p_in.at(flattenIndex(x - 1 ,y, grid_x));
  355. mass = inv_masses.at(flattenIndex(x - 1, y, grid_x));
  356. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  357. offset = distance - (cloth_x/(grid_x - 1.0f));
  358. float mass_end = (beginning_mass / (mass + beginning_mass));
  359. particle3 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  360.  
  361. }
  362. if(y > 0)
  363. {
  364. feder = p_in.at(flattenIndex(x, y - 1, grid_x));
  365. mass = inv_masses.at(flattenIndex(x , y - 1, grid_x));
  366. distance = length((p_in.at(flattenIndex(x,y,grid_x)) - feder));
  367. offset = distance - (cloth_y/(grid_y - 1.0f));
  368. float mass_end = (beginning_mass / (mass + beginning_mass));
  369. particle4 = offset * normalize(feder - p_in.at(flattenIndex(x,y,grid_x))) * mass_end;
  370. }
  371. p_out.at(flattenIndex(x,y,grid_x)) = p_out.at(flattenIndex(x,y,grid_x)) + ((particle1 + particle2 + particle3 + particle4)*fixup_percent);
  372.  
  373. }
  374.  
  375.  
  376.  
  377.  
  378. }
  379. ////////////////////////////////////////////////
  380. //////////////// fix collission ////////////////
  381. ////////////////////////////////////////////////
  382. for(unsigned int itr = 0; itr < obstacles.size(); ++itr)
  383. {
  384. fixCollision(p_out.at(flattenIndex(x,y,grid_x)), obstacles.at(itr));
  385. }
  386. }
  387. }
  388.  
  389. }
  390.  
  391. void fixCollision(float3& particle_position, const Sphere& sphere) {
  392. // TODO: resolve particle/obstacle collision
  393. //
  394. // Check if the particle is inside the sphere.
  395. // If so, move the particle out of the sphere (along the sphere normal).
  396. //
  397. // Parameters:
  398. // particle_position: position of the particle
  399. // sphere: spherical obstacle containg the position and radius
  400. if(length(particle_position - sphere.position) < sphere.radius)
  401. {
  402. float3 temp = normalize(particle_position - sphere.position);
  403. particle_position = sphere.position + temp * sphere.radius;
  404.  
  405. }
  406.  
  407. }
  408.  
  409. void simulationStep(std::array<std::vector<float3>, 3>& p_buffers, int& next,
  410. int& current, int& previous, int grid_x, int grid_y,
  411. float cloth_x, float cloth_y,
  412. const std::vector<float>& inv_masses,
  413. std::vector<float3>& normals, const float3& gravity,
  414. const float3& wind_force, float damping,
  415. float fixup_percent, int fixup_iterations,
  416. const std::vector<Sphere>& obstacles, float dt,
  417. bool apply_structural_fixup, bool apply_shear_fixup,
  418. bool apply_flexion_fixup) {
  419. // TODO: implement the simulation step
  420. //
  421. // 1. Calculate particle normals => calcNormals()
  422. // 2. Perform Verlet Integration => verletIntegration()
  423. // 3. Perform fixup steps => fixupStep()
  424. //
  425. // Verlet Integration:
  426. // You will need three position buffers, since the verlet integration needs
  427. // the current und previous positions. The integrated position shall be
  428. // written to the 'next' position buffer. Make sure to update the next,
  429. // current, previous indices! e.g. after the integration step: next ->
  430. // current, current -> last and last -> next
  431. //
  432. // Fixup:
  433. // Repeatedly execute the FixUp step after each integration
  434. // ('fixup_iterations' times). Make sure to update your position buffer
  435. // indices in the right way!
  436. //
  437. // Make sure that 'current' points to the right position buffer before you
  438. // return!
  439. //
  440. // Parameters:
  441. // p_buffers: 3 position buffers
  442. // next: index of next position buffer
  443. // current: index of current position buffer
  444. // previous: index of previous position buffer
  445. // grid_x, grid_y: particle-grid dimensions
  446. // cloth_x, cloth_y: cloth size
  447. // inv_masses: inverse particle masses
  448. // normals: particle normals
  449. // gravity: gravity vector
  450. // wind_force: wind force
  451. // damp: damping factor for verlet integration
  452. // fixup_percent: fixup percent [0..1]
  453. // fixup_iterations: how often the fixup step should be executed
  454. // obstacles: obstacle vector
  455. // dt: timestep
  456. //
  457. // apply_structural_fixup: apply structural fixup
  458. // (needs to be passed unmodified to fixupStep for automatic testing)
  459. //
  460. // apply_shear_fixup: apply shear fixup
  461. // (needs to be passed unmodified to fixupStep for automatic testing)
  462. //
  463. // apply_flexion_fixup: apply flexion fixup
  464. // (needs to be passed unmodified to fixupStep for automatic testing)
  465. //
  466.  
  467. // Simply make cloth fall down. You will want to replace that ;)
  468. calcNormals(normals, p_buffers[current], grid_x, grid_y);
  469. verletIntegration(p_buffers[next], p_buffers[current], p_buffers[previous], normals, inv_masses, damping,
  470. gravity, wind_force, dt);
  471.  
  472. int save = next;
  473. next = previous;
  474. previous = current;
  475. current = save;
  476.  
  477.  
  478. for(unsigned int iteration = 0; iteration < fixup_iterations; iteration++)
  479. {
  480. fixupStep(p_buffers[next], p_buffers[current], grid_x, grid_y, cloth_x, cloth_y, inv_masses, fixup_percent,
  481. obstacles, apply_structural_fixup, apply_shear_fixup, apply_flexion_fixup);
  482. int save = current;
  483. current = next;
  484. next = save;
  485.  
  486. }
  487. //for (auto& p : p_buffers[current]) p += gravity * dt;
  488. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement