PfTri _pf_tri(v2f radii, bool line, PfCorner hypotenuse) { const float radians = tri_angle(&radii, hypotenuse); return (PfTri) { .radii = radii, .line = line, .hypotenuse = hypotenuse, .radians = radians, .m = pf_tri_slope(&radii, hypotenuse), .proj = projection_vector(radians), .normal = tri_normal(&radii, hypotenuse), .sin = sinf(radians), .cos = cosf(radians), }; } PfGroup _pf_platform() { return (PfGroup) { .tag = PF_GROUP_PLATFORM, .platform = (PfPlatform) { .allow = 0, .convey = _v2f(0,0), .left = NULL, .right = NULL, }, }; } PfBody _pf_body() { return (PfBody) { .mode = PF_MODE_DYNAMIC, .shape = (PfShape) { .tag = PF_SHAPE_CIRCLE, .radius = 0 }, .pos = _v2f(0,0), .group.object.parent = NULL, .group.object.check_parent = false, .dpos = _v2f(0,0), .in = { .impulse = fillv2f(0), .decay = fillv2f(0.5), .cap = fillv2f(1000), }, .ex = { .impulse = fillv2f(0), .decay = fillv2f(0.3), .cap = fillv2f(1000), }, .gravity = {
static errcode GetRecurseObject(SceneHandle scene, FILE *dfile, RotMat rmat, TransMat tmat) { char token[256], objname[128], name[128], texname[128], urlname[100]; RotMat localrmat, newrmat; TransMat localtmat, newtmat; float txrepa, txrepb, a, b; int numvert, numsurf, surf, materialnum, numrefs, numkids, data; int i, j; apivector * vertexarray = NULL; apivector * normalarray = NULL; int * refarray = NULL; tri_list * tlist = NULL; errcode rc = PARSENOERR; /* zero out variables */ numvert = numsurf = surf = materialnum = numrefs = numkids = data = 0; RmatIdentity(localrmat); localtmat[0] = 0.0; localtmat[1] = 0.0; localtmat[2] = 0.0; fscanf(dfile, "%s", objname); fscanf(dfile, "%s", token); if (!stringcmp(token, "NAME")) { GetAC3DString(dfile, name); fscanf(dfile, "%s", token); } if (!stringcmp(token, "DATA")) { fscanf(dfile, "%d", &data); fscanf(dfile, "%s", token); } if (!stringcmp(token, "TEXTURE")) { fscanf(dfile, "%s", texname); fscanf(dfile, "%s", token); } if (!stringcmp(token, "TEXREP")) { fscanf(dfile, "%f %f", &txrepa, &txrepb); fscanf(dfile, "%s", token); } if (!stringcmp(token, "ROT")) { for (j=0; j<3; j++) { for(i=0; i<3; i++) { fscanf(dfile, "%f", &localrmat[j][i]); } } fscanf(dfile, "%s", token); } if (!stringcmp(token, "LOC")) { for (j=0; j<3; j++) { fscanf(dfile, "%f", &localtmat[j]); } fscanf(dfile, "%s", token); } if (!stringcmp(token, "ROT")) { for (j=0; j<3; j++) { for(i=0; i<3; i++) { fscanf(dfile, "%f", &localrmat[j][i]); } } fscanf(dfile, "%s", token); } /* Perform Matrix Transforms for local coordinate system */ RmatTmatMult(newtmat, rmat, localtmat); newtmat[0] += tmat[0]; newtmat[1] += tmat[1]; newtmat[2] += tmat[2]; RmatMult(newrmat, rmat, localrmat); if (!stringcmp(token, "URL")) { fscanf(dfile, "%s", urlname); fscanf(dfile, "%s", token); } if (!stringcmp(token, "TEXTURE")) { GetAC3DString(dfile, token); fscanf(dfile, "%s", token); } if (!stringcmp(token, "NUMVERT")) { TransMat vtx, tvtx; fscanf(dfile, "%d", &numvert); vertexarray = (apivector *) malloc(numvert * sizeof(apivector)); normalarray = (apivector *) malloc(numvert * sizeof(apivector)); /* initialize the normal array */ clear_normals(normalarray, numvert); /* load and transform vertices */ for (i=0; i<numvert; i++) { fscanf(dfile, "%f %f %f", &vtx[0], &vtx[1], &vtx[2]); /* transform vertices */ RmatTmatMult(tvtx, newrmat, vtx); vertexarray[i].x = tvtx[0] + newtmat[0]; vertexarray[i].y = tvtx[1] + newtmat[1]; vertexarray[i].z = tvtx[2] + newtmat[2]; } fscanf(dfile, "%s", token); } if (!stringcmp(token, "NUMSURF")) { fscanf(dfile, "%d", &numsurf); fscanf(dfile, "%s", token); for (j=0; j<numsurf; j++) { numrefs = surf = materialnum = 0; if (!stringcmp(token, "SURF")) { /* COMPILER BUG!!! */ /* This is messed up friend.. */ /* if done using a normal fscanf() the program nails its */ /* stack, and seg faults. This *must* be a compiler or */ /* libc bug. */ #if 1 fscanf(dfile, "%s", token); sscanf(token, "%x", &surf); #else fscanf(dfile, "%x", &surf); #endif fscanf(dfile, "%s", token); } if (!stringcmp(token, "MAT")) { fscanf(dfile, "%d", &materialnum); fscanf(dfile, "%s", token); } if (!stringcmp(token, "REFS")) fscanf(dfile, "%d", &numrefs); else return (rc |= PARSEBADSYNTAX); refarray = (int *) malloc(numrefs * sizeof(int)); for (i=0; i<numrefs; i++) { fscanf(dfile, "%d %f %f", &refarray[i], &a, &b); } /* generate triangles/polygons here */ /* ignore all lines, points and other non-surface primatives */ if ((surf & 0xF) == 0) { int v0, vold, vnew; apivector trinorm; /* add in surface normal to vertices */ trinorm = tri_normal(&vertexarray[refarray[1]], &vertexarray[refarray[0]], &vertexarray[refarray[2]]); for (i=0; i<numrefs; i++) { normalarray[refarray[i]].x += trinorm.x; normalarray[refarray[i]].y += trinorm.y; normalarray[refarray[i]].z += trinorm.z; } v0 = refarray[0]; vold = refarray[1]; for (i=2; i<numrefs; i++) { vnew = refarray[i]; tlist_add_tri(&tlist, vold, v0, vnew, surf & 0x10, materialnum); vold = vnew; } } free(refarray); refarray=NULL; fscanf(dfile, "%s", token); } } if ((vertexarray != NULL) && (normalarray != NULL)) { /* now that all vertex normals have been summed, we'll renormalize */ renormalize_normals(normalarray, numvert); gen_triangles(scene, tlist, vertexarray, normalarray); tlist_delete(&tlist); } /* free vertex and normal arrays */ if (vertexarray != NULL) free(vertexarray); vertexarray = NULL; if (normalarray != NULL) free(normalarray); normalarray = NULL; if (!stringcmp(token, "KIDS")) fscanf(dfile, "%d", &numkids); else return (rc |= PARSEBADSYNTAX); /* Recurse to handle child geometry */ while (numkids > 0) { rc |= GetString(dfile, "OBJECT"); rc |= GetRecurseObject(scene, dfile, newrmat, newtmat); numkids--; } return rc; }
// returns true if triangle intersects plane, int1 and int2 will be set // to the intersection points // returns false if all points are above or below the plane int write_sliced_tri(FILE *f, vec *p1, vec *p2, vec *p3, int rev, vec *p, // point that lies in the slicing plane vec *n, // normal of slicing plane, keep points in the direction of normal vec *int1, // output, intersecting pt1, returned only if intersection occurs vec *int2, // output, intersecting pt2, returned only if intersection occurs int *tris) // output, number of tris written { vec trin; tri_normal(p1,p2,p3,rev,&trin); point_state_t state1; point_state_t state2; point_state_t state3; state1 = point_state(p1,p,n); state2 = point_state(p2,p,n); state3 = point_state(p3,p,n); if((state1 == ABOVE || state1 == ON) && (state2 == ABOVE || state2 == ON) && (state3 == ABOVE || state3 == ON)) { // all points are above or on plane, write tri normally write_tri(f,p1,p2,p3,rev); *tris = 1; return 0; } else if((state1 == BELOW || state1 == ON) && (state2 == BELOW || state2 == ON) && (state3 == BELOW || state3 == ON)) { // all points are below or on plane, cull entire tri *tris = 0; return 0; } else { // triangle intersects plane if(state1 == ON) { vec tmp1,tmp2; float r; vec_copy(p1, int1); vec_sub(p2,p3,&tmp1); vec_sub(p,p3,&tmp2); r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1); int2->x = p3->x + r*tmp1.x; int2->y = p3->y + r*tmp1.y; int2->z = p3->z + r*tmp1.z; if(state2 == ABOVE) { write_tri(f,p1,p2,int2,rev); } else { write_tri(f,p1,int2,p3,rev); } *tris = 1; return 1; } if(state2 == ON) { vec tmp1,tmp2; float r; vec_copy(p2, int1); vec_sub(p1,p3,&tmp1); vec_sub(p,p3,&tmp2); r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1); int2->x = p3->x + r*tmp1.x; int2->y = p3->y + r*tmp1.y; int2->z = p3->z + r*tmp1.z; if(state1 == ABOVE) { write_tri(f,p1,p2,int2,rev); } else { write_tri(f,p2,p3,int2,rev); } *tris = 1; return 1; } if(state3 == ON) { vec tmp1,tmp2; float r; vec_copy(p3, int2); vec_sub(p1,p2,&tmp1); vec_sub(p,p2,&tmp2); r = vec_dot(n,&tmp2)/vec_dot(n,&tmp1); int1->x = p2->x + r*tmp1.x; int1->y = p2->y + r*tmp1.y; int1->z = p2->z + r*tmp1.z; if(state1 == ABOVE) { write_tri(f,p1,int1,p3,rev); } else { write_tri(f,int1,p2,p3,rev); } *tris = 1; return 1; } if((state1 == ABOVE && state2 == ABOVE) || (state1 == BELOW && state2 == BELOW)) { vec tmp1,tmp2,tmp3; float r1,r2; vec_sub(p2,p3,&tmp1); vec_sub(p1,p3,&tmp2); vec_sub(p,p3,&tmp3); r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1); r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2); int1->x = p3->x + r1*tmp1.x; int1->y = p3->y + r1*tmp1.y; int1->z = p3->z + r1*tmp1.z; int2->x = p3->x + r2*tmp2.x; int2->y = p3->y + r2*tmp2.y; int2->z = p3->z + r2*tmp2.z; if(state3 == ABOVE) { write_tri(f,int1,p3,int2,rev); *tris = 1; } else { write_quad(f,p1,p2,int1,int2,rev); *tris = 2; } return 1; } if((state2 == ABOVE && state3 == ABOVE) || (state2 == BELOW && state3 == BELOW)) { vec tmp1,tmp2,tmp3; float r1,r2; vec_sub(p2,p1,&tmp1); vec_sub(p3,p1,&tmp2); vec_sub(p,p1,&tmp3); r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1); r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2); int1->x = p1->x + r1*tmp1.x; int1->y = p1->y + r1*tmp1.y; int1->z = p1->z + r1*tmp1.z; int2->x = p1->x + r2*tmp2.x; int2->y = p1->y + r2*tmp2.y; int2->z = p1->z + r2*tmp2.z; if(state1 == ABOVE) { write_tri(f,p1,int1,int2,rev); *tris = 1; } else { write_quad(f,int1,p2,p3,int2,rev); *tris = 2; } return 1; } if((state1 == ABOVE && state3 == ABOVE) || (state1 == BELOW && state3 == BELOW)) { vec tmp1,tmp2,tmp3; float r1,r2; vec_sub(p1,p2,&tmp1); vec_sub(p3,p2,&tmp2); vec_sub(p,p2,&tmp3); r1 = vec_dot(n,&tmp3)/vec_dot(n,&tmp1); r2 = vec_dot(n,&tmp3)/vec_dot(n,&tmp2); int1->x = p2->x + r1*tmp1.x; int1->y = p2->y + r1*tmp1.y; int1->z = p2->z + r1*tmp1.z; int2->x = p2->x + r2*tmp2.x; int2->y = p2->y + r2*tmp2.y; int2->z = p2->z + r2*tmp2.z; if(state2 == ABOVE) { write_tri(f,int1,p2,int2,rev); *tris = 1; } else { write_quad(f,p1,int1,int2,p3,rev); *tris = 2; } return 1; } } *tris = 0; return 0; }