for(size_t i=0; i<hair.size(); i++) {
hair[i].pos = hair[i].spawn_pt + hair[i].spawn_dir * hair_length;
-
- /* orthonormal basis */
- Vec3 vk = hair[i].spawn_dir;
- Vec3 vi = Vec3(1, 0, 0);
- if(fabs(vk.x > 0.99)) {
- vi = Vec3(0, -1, 0);
- }
- Vec3 vj = normalize(cross(vk, vi));
- vi = cross(vj, vk);
-
- /* identity when the hair points to the z axis */
- Mat4 basis = Mat4(vi, vj, vk);
-
- for(int j=0; j<3; j++) {
- float angle = (float)j / 3.0 * 2 * M_PI;
- /* dir of each anchor relative to hair root */
- Vec3 dir = Vec3(cos(angle), sin(angle), 0);
- dir = basis * dir;
- hair[i].anchor_dirs[j] = hair[i].pos + dir - hair[i].spawn_pt;
- }
}
return true;
}
/*
glColor3f(1, 1, 0);
glVertex3f(hair[i].pos.x, hair[i].pos.y, hair[i].pos.z);
- Vec3 end = hair[i].pos + dbg_force * 2.0;
- glVertex3f(end.x, end.y, end.z);
+ Vec3 fend = hair[i].pos + dbg_force * 2.0;
+ glVertex3f(fend.x, fend.y, fend.z);
*/
}
glEnd();
Vec3 accel = force; /* mass 1 */
hair[i].velocity += ((-hair[i].velocity * DAMPING) + accel) * dt;
- hair[i].pos += hair[i].velocity * dt;
+ Vec3 new_pos = hair[i].pos + hair[i].velocity * dt;
+
+ /* collision detection with the head */
+ Vec3 normal = xform.upper3x3() * hair[i].spawn_dir;
+ Vec3 root = xform * hair[i].spawn_pt;
+ Vec3 dir = new_pos - root;
+
+ normal.normalize();
+
+ /* angle that will cause the hair to be rendered inside the head */
+ float d = dot(dir, normal);
+ if(d < 0) {
+ new_pos += -d * normal;
+ }
+
+ hair[i].pos = handle_collision(new_pos);
dbg_force = force;
}
}
+
+void Hair::add_collider(CollSphere *cobj) {
+ colliders.push_back(cobj);
+}
+
+Vec3 Hair::handle_collision(const Vec3 &v) const
+{
+ /* if we transform the center and the radius of the collider sphere
+ * we might end up with a spheroid, so better just multiply the
+ * position with the inverse transform before check for collisions :*/
+
+ Vec3 new_v = inverse(xform) * v;
+
+ for(size_t i=0; i<colliders.size(); i++) {
+ if(colliders[i]->contains(new_v)) {
+ new_v = colliders[i]->project_surf(new_v);
+ }
+ }
+ return xform * new_v;
+}