Exemple #1
0
Fichier : pf.c Projet : jxv/pf
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;
}