static void applyForces(struct particle_system *ps, struct particle *p) { int i = 0; vec3 force; vec3 dir; float m, d, s; vec3Copy(p->dir, p->acc); do { switch(ps->forces[i].type) { case PARTICLE_FORCE_DIRECTIONAL: vec3Copy(ps->forces[i].dir, force); break; case PARTICLE_FORCE_FLUID: s = vec3Mag(p->acc); vec3Copy(p->acc, force); vec3Normalize(force, force); vec3Mul(force, -ps->forces[i].value*s*s, force); break; case PARTICLE_FORCE_ATTRACTION: vec3Sub(ps->forces[i].loc, p->loc, dir); d = vec3Mag(dir); vec3Normalize(dir, dir); m = 0.00001*ps->forces[i].value*p->mass / (d*d); vec3Mul(dir, m, force); break; } vec3Add(p->acc, force, p->acc); } while(++i < ps->nbforces); vec3Div(p->acc, p->mass, p->acc); vec3Add(p->vel, p->acc, p->vel); vec3Add(p->loc, p->vel, p->loc); }
mat4* lookAt(mat4* pOut, const vec3* pEye, const vec3* pCenter, const vec3* pUp) { vec3 f; avec3_subtract(&f, pCenter, pEye); vec3Normalize(&f, &f); vec3 s; vec3Cross(&s, &f, pUp); vec3Normalize(&s, &s); vec3 u; vec3Cross(&u, &s, &f); pOut->mat[0] = s.x; pOut->mat[1] = u.x; pOut->mat[2] = -f.x; pOut->mat[3] = 0.0; pOut->mat[4] = s.y; pOut->mat[5] = u.y; pOut->mat[6] = -f.y; pOut->mat[7] = 0.0; pOut->mat[8] = s.z; pOut->mat[9] = u.z; pOut->mat[10] = -f.z; pOut->mat[11] = 0.0; pOut->mat[12] = -vec3Dot(&s, pEye); pOut->mat[13] = -vec3Dot(&u, pEye); pOut->mat[14] = vec3Dot(&f, pEye); pOut->mat[15] = 1.0; return pOut; }
// Inverse edge length weighted method. As described in Real-time rendering (3rd ed.) p.546. // Ref: Max, N. L., (1999) 'Weights for computing vertex normals from facet normals' // in Journal of grahics tools, vol.4, no.2, pp.1-6. static GLfloat* meshGenerateNormals(int num_verts, int num_elems, const GLfloat *verts, const GLushort *elems) { GLfloat *norms = (GLfloat*) calloc(3*num_verts, sizeof(GLfloat)); GLfloat e1[3], e2[3], no[3]; for (int i = 0; i < num_elems; i += 3) { for (int j = 0; j < 3; ++j) { int a = 3*elems[i+j]; int b = 3*elems[i+((j+1)%3)]; int c = 3*elems[i+((j+2)%3)]; vec3Sub(e1, &verts[c], &verts[b]); vec3Sub(e2, &verts[a], &verts[b]); vec3Cross(no, e1, e2); double d = vec3Length2(e1) * vec3Length2(e2); vec3DivScalar(no, no, d); vec3Add(&norms[b], &norms[b], no); } } for (int i = 0; i < 3*num_verts; i += 3) { vec3Normalize(&norms[i], &norms[i]); } return norms; }
vec3 vec3MakeWithPoints(vec3 start, vec3 end) { vec3 ret; ret.x = end.x - start.x; ret.y = end.y - start.y; ret.z = end.z - start.z; vec3Normalize(&ret); return ret; }
void transformComputeAverageNormals(unsigned int *idx, int nbidx, float *vtx, int nbvtx, float *nrm, int nrmpervtx) { unsigned int v1, v2, v3; float *a, *b, *c; vec3 vnormal; int i; bzero(nrm, nbvtx*3*sizeof(float)); for(i = 0; i < nbidx; i++) { v1 = idx[i*3]; v2 = idx[i*3+1]; v3 = idx[i*3+2]; a = vtx + v1 * 3; b = vtx + v2 * 3; c = vtx + v3 * 3; vec3Normal(vnormal, a, b, c); nrm[v1*3] += vnormal[0]; nrm[v1*3+1] += vnormal[1]; nrm[v1*3+2] += vnormal[2]; nrm[v2*3] += vnormal[0]; nrm[v2*3+1] += vnormal[1]; nrm[v2*3+2] += vnormal[2]; nrm[v3*3] += vnormal[0]; nrm[v3*3+1] += vnormal[1]; nrm[v3*3+2] += vnormal[2]; } for(i = 0; i < nbvtx; i++) { vec3Normalize(&nrm[i*3], &nrm[i*3]); } }