7 static void step(struct rsim_world *rsim, struct rsim_rope *rope, float dt);
9 int rsim_init(struct rsim_world *rsim)
12 cgm_vcons(&rsim->grav, 0, -9.807, 0);
17 void rsim_destroy(struct rsim_world *rsim)
20 struct rsim_rope *rope = rsim->ropes;
21 rsim->ropes = rsim->ropes->next;
26 int rsim_add_rope(struct rsim_world *rsim, struct rsim_rope *rope)
28 rope->next = rsim->ropes;
33 static inline struct rsim_spring *getspring(struct rsim_rope *rope, int aidx, int bidx)
35 struct rsim_spring *spr = rope->springs + aidx * rope->num_masses + bidx;
36 return *(uint32_t*)&spr->rest_len == 0xffffffff ? 0 : spr;
39 /* actual step function, called by rsim_step in a loop to microstep or once if
40 * microstepping is disabled
42 static void step(struct rsim_world *rsim, struct rsim_rope *rope, float dt)
46 cgm_vec3 npos, faccel, dir;
47 float inv_damp = rsim->damping == 0.0f ? 1.0f : (1.0f - rsim->damping);
48 struct rsim_mass *mass;
49 struct rsim_spring *spr;
51 /* for each mass, add spring forces to every other mass it's connected to */
52 for(i=0; i<rope->num_masses; i++) {
53 for(j=0; j<rope->num_masses; j++) {
54 if(i == j || !(spr = getspring(rope, i, j))) {
58 dir = rope->masses[i].p;
59 cgm_vsub(&dir, &rope->masses[j].p);
61 len = cgm_vlength(&dir);
69 fmag = (len - spr->rest_len) * spr->k;
71 printf("%d-%d fmag: %f\n", i, j, fmag);
72 if(fmag > 20) asm volatile("int $3");
75 //assert(rope->masses[j].m != 0.0f);
76 cgm_vscale(&dir, fmag / rope->masses[j].m);
77 cgm_vadd(&rope->masses[j].f, &dir);
83 for(i=0; i<rope->num_masses; i++) {
89 /* add constant forces to accumulated mass force */
90 cgm_vadd(&mass->f, &rsim->grav);
92 faccel = rsim->extforce;
93 cgm_vscale(&faccel, 1.0f / mass->m);
94 cgm_vadd(&mass->f, &rsim->extforce);
96 mass->v.x = (mass->v.x - mass->v.x * inv_damp * dt) + mass->f.x * dt;
97 mass->v.y = (mass->v.y - mass->v.y * inv_damp * dt) + mass->f.y * dt;
98 mass->v.z = (mass->v.z - mass->v.z * inv_damp * dt) + mass->f.z * dt;
100 /* zero out the accumulated forces for next iter */
101 mass->f.x = mass->f.y = mass->f.z = 0.0f;
104 npos.x = mass->p.x + mass->v.x * dt;
105 npos.y = mass->p.y + mass->v.y * dt;
106 npos.z = mass->p.z + mass->v.z * dt;
108 /* TODO collisions */
115 void rsim_step(struct rsim_world *rsim, float dt)
117 struct rsim_rope *rope = rsim->ropes;
119 if(rsim->udt > 0.0f) {
121 float dt_acc = rsim->udelta_acc;
125 step(rsim, rope, rsim->udt);
130 rsim->udelta_acc = dt_acc - dt;
133 step(rsim, rope, dt);
139 struct rsim_rope *rsim_alloc_rope(int nmasses)
141 struct rsim_rope *rope;
143 if(!(rope = malloc(sizeof *rope))) {
146 if(rsim_init_rope(rope, nmasses) == -1) {
153 void rsim_free_rope(struct rsim_rope *rope)
155 rsim_destroy_rope(rope);
159 int rsim_init_rope(struct rsim_rope *rope, int nmasses)
161 memset(rope, 0, sizeof *rope);
163 if(!(rope->masses = calloc(nmasses, sizeof *rope->masses))) {
166 rope->num_masses = nmasses;
168 if(!(rope->springs = malloc(nmasses * nmasses * sizeof *rope->springs))) {
172 memset(rope->springs, 0xff, nmasses * nmasses * sizeof *rope->springs);
176 void rsim_destroy_rope(struct rsim_rope *rope)
182 int rsim_set_rope_spring(struct rsim_rope *rope, int ma, int mb, float k, float rlen)
185 struct rsim_spring *spr, *rps;
187 if(ma == mb || ma < 0 || ma >= rope->num_masses || mb < 0 || mb >= rope->num_masses) {
191 if(rlen == RSIM_RLEN_DEFAULT) {
192 dir = rope->masses[ma].p;
193 cgm_vsub(&dir, &rope->masses[mb].p);
194 rlen = cgm_vlength(&dir);
197 spr = rope->springs + ma * rope->num_masses + mb;
198 rps = rope->springs + mb * rope->num_masses + ma;
199 spr->k = rps->k = fabs(k);
200 spr->rest_len = rps->rest_len = rlen;
204 int rsim_have_spring(struct rsim_rope *rope, int ma, int mb)
206 return getspring(rope, ma, mb) ? 1 : 0;
209 int rsim_freeze_rope_mass(struct rsim_rope *rope, struct rsim_mass *m)
211 if(m->fixed) return -1;
217 int rsim_unfreeze_rope_mass(struct rsim_rope *rope, struct rsim_mass *m)
219 if(!m->fixed) return -1;