cloth2
changeset 1:dc15b741486c
exploding cloth
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 11 Jan 2016 20:24:13 +0200 |
parents | ef0c22554406 |
children | b4b8f736332b |
files | src/cloth.cc src/cloth.h src/main.cc |
diffstat | 3 files changed, 83 insertions(+), 15 deletions(-) [+] |
line diff
1.1 --- a/src/cloth.cc Mon Jan 11 16:51:16 2016 +0200 1.2 +++ b/src/cloth.cc Mon Jan 11 20:24:13 2016 +0200 1.3 @@ -9,6 +9,7 @@ 1.4 mass = 1.0; 1.5 elast = 0.8; 1.6 spring_k = 1.0; 1.7 + damping = 0.01; 1.8 grav = Vector3(0, -9, 0); 1.9 } 1.10 1.11 @@ -31,7 +32,7 @@ 1.12 masses[idx].pos.x = (float)j * dx - width / 2.0; 1.13 masses[idx].pos.y = 0; 1.14 masses[idx].pos.z = (float)i * dy - height / 2.0; 1.15 - masses[idx].fixed = i == 0 && (j == 0 || j == x - 1); // XXX debug hack 1.16 + masses[idx].fixed = i == 0; // XXX debug hack 1.17 ++idx; 1.18 } 1.19 } 1.20 @@ -43,10 +44,10 @@ 1.21 conn[idx][idx] = -1; 1.22 1.23 // connect node to its neighbors 1.24 - for(int ni=0; ni<5; ni++) { 1.25 - for(int nj=0; nj<5; nj++) { 1.26 - int nx = j + nj - 2; 1.27 - int ny = i + ni - 2; 1.28 + for(int ni=0; ni<3; ni++) { 1.29 + for(int nj=0; nj<3; nj++) { 1.30 + int nx = j + nj - 1; 1.31 + int ny = i + ni - 1; 1.32 1.33 if(!nx && !ny) continue; 1.34 if(nx < 0 || nx >= x || ny < 0 || ny >= y) continue; 1.35 @@ -63,6 +64,36 @@ 1.36 } 1.37 } 1.38 1.39 +void Cloth::set_mass(float m) 1.40 +{ 1.41 + mass = m; 1.42 +} 1.43 + 1.44 +void Cloth::set_elasticity(float e) 1.45 +{ 1.46 + elast = e; 1.47 +} 1.48 + 1.49 +void Cloth::set_spring_constant(float k) 1.50 +{ 1.51 + spring_k = k; 1.52 +} 1.53 + 1.54 +void Cloth::set_damping(float d) 1.55 +{ 1.56 + damping = d; 1.57 +} 1.58 + 1.59 +void Cloth::set_gravity(const Vector3 &g) 1.60 +{ 1.61 + grav = g; 1.62 +} 1.63 + 1.64 +void Cloth::set_force(const Vector3 &f) 1.65 +{ 1.66 + forces = f; 1.67 +} 1.68 + 1.69 void Cloth::transform(const Matrix4x4 &xform) 1.70 { 1.71 for(size_t i=0; i<masses.size(); i++) { 1.72 @@ -79,25 +110,35 @@ 1.73 { 1.74 int num_masses = (int)masses.size(); 1.75 1.76 + Vector3 *newp = new Vector3[num_masses]; 1.77 + 1.78 for(int i=0; i<num_masses; i++) { 1.79 - if(masses[i].fixed) continue; 1.80 - 1.81 - Vector3 newpos = masses[i].pos + masses[i].vel * dt; 1.82 + if(masses[i].fixed) { 1.83 + newp[i] = masses[i].pos; 1.84 + continue; 1.85 + } 1.86 1.87 Vector3 force = grav + forces; 1.88 1.89 for(int j=0; j<num_masses; j++) { 1.90 - if(conn[i][j] <= 0.0) continue; // skip unconnected 1.91 + if(i == j || conn[i][j] <= 0.0) { 1.92 + continue; // skip unconnected 1.93 + } 1.94 1.95 Vector3 dir = masses[j].pos - masses[i].pos; 1.96 float dist = length(dir); 1.97 + float disp = dist - conn[i][j]; 1.98 + if(fabs(disp) < 1e-5) disp = 0.0f; 1.99 1.100 // apply an impulse based on the displacement from the original state 1.101 - force += dir * (dist - conn[i][j]) * spring_k; 1.102 + force += dir * ((disp * spring_k) / dist * 0.5); 1.103 } 1.104 1.105 // update the velocity by integrating the accumulation of all forces 1.106 - masses[i].vel += force * dt; 1.107 + Vector3 accel = force / mass; 1.108 + masses[i].vel = masses[i].vel * (1.0 - damping) + accel * dt; 1.109 + 1.110 + Vector3 newpos = masses[i].pos + masses[i].vel * dt; 1.111 1.112 Ray ray; 1.113 ray.origin = masses[i].pos; 1.114 @@ -108,8 +149,15 @@ 1.115 newpos = pt.pos; 1.116 masses[i].vel = reflect(masses[i].vel, pt.normal) * elast; // TODO collider elasticity 1.117 } 1.118 - masses[i].pos = newpos; 1.119 + //masses[i].pos = newpos; 1.120 + newp[i] = newpos; 1.121 } 1.122 + 1.123 + for(int i=0; i<num_masses; i++) { 1.124 + masses[i].pos = newp[i]; 1.125 + } 1.126 + 1.127 + delete [] newp; 1.128 } 1.129 1.130 bool Cloth::find_collision(const Ray &ray, HitPoint *hit) const
2.1 --- a/src/cloth.h Mon Jan 11 16:51:16 2016 +0200 2.2 +++ b/src/cloth.h Mon Jan 11 20:24:13 2016 +0200 2.3 @@ -16,6 +16,7 @@ 2.4 private: 2.5 float mass, elast; // global mass attributes 2.6 float spring_k; // spring constant for all springs 2.7 + float damping; 2.8 Vector3 grav, forces; 2.9 2.10 std::vector<ClothMass> masses; 2.11 @@ -30,6 +31,13 @@ 2.12 2.13 void create_rect(int x, int y, float width, float height); 2.14 2.15 + void set_mass(float m); 2.16 + void set_elasticity(float e); 2.17 + void set_spring_constant(float k); 2.18 + void set_damping(float d); 2.19 + void set_gravity(const Vector3 &g); 2.20 + void set_force(const Vector3 &f); 2.21 + 2.22 void transform(const Matrix4x4 &xform); 2.23 2.24 void add_collider(Object *o);
3.1 --- a/src/main.cc Mon Jan 11 16:51:16 2016 +0200 3.2 +++ b/src/main.cc Mon Jan 11 20:24:13 2016 +0200 3.3 @@ -19,7 +19,7 @@ 3.4 void mouse(int bn, int st, int x, int y); 3.5 void motion(int x, int y); 3.6 3.7 -float cam_theta, cam_phi, cam_dist = 8; 3.8 +float cam_theta, cam_phi = 25, cam_dist = 10; 3.9 3.10 Cloth cloth; 3.11 3.12 @@ -55,13 +55,17 @@ 3.13 //glEnable(GL_LIGHTING); 3.14 glEnable(GL_LIGHT0); 3.15 3.16 - cloth.create_rect(32, 32, 10, 10); 3.17 + cloth.create_rect(4, 4, 10, 10); 3.18 3.19 Matrix4x4 xform = Matrix4x4(1, 0, 0, 0, 3.20 0, 1, 0, 0, 3.21 0, 0, 1, 0, 3.22 - 0, 1, 0, 1); 3.23 + 0, 1, 1, 1); 3.24 cloth.transform(xform); 3.25 + cloth.set_mass(0.1); 3.26 + cloth.set_spring_constant(0.1); 3.27 + cloth.set_gravity(Vector3(0, -0.1, 0)); 3.28 + cloth.set_damping(0.1); 3.29 3.30 3.31 return true; 3.32 @@ -73,6 +77,14 @@ 3.33 3.34 void display() 3.35 { 3.36 + static unsigned int prev_upd; 3.37 + unsigned int msec = glutGet(GLUT_ELAPSED_TIME); 3.38 + 3.39 + if(!prev_upd) prev_upd = msec; 3.40 + float dt = (msec - prev_upd) / 1000.0f; 3.41 + 3.42 + cloth.step(dt); 3.43 + 3.44 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 3.45 3.46 glMatrixMode(GL_MODELVIEW);