Example #1
0
/*!
 * Find the bounding box of a mesh object.
 *
 * \param mesh The mesh object
 * \param min Returned bounding box
 * \param max Returned bounding box
 *
 * \ingroup mesh
 */
void
lib3ds_mesh_bounding_box(Lib3dsMesh *mesh, Lib3dsVector min, Lib3dsVector max)
{
  unsigned i,j;
  Lib3dsFloat v;

  if (!mesh->points) {
    lib3ds_vector_zero(min);
    lib3ds_vector_zero(max);
    return;
  }
 
  lib3ds_vector_copy(min, mesh->pointL[0].pos);
  lib3ds_vector_copy(max, mesh->pointL[0].pos);
  for (i=1; i<mesh->points; ++i) {
    for (j=0; j<3; ++j) {
      v=mesh->pointL[i].pos[j];
      if (v<min[j]) {
        min[j]=v;
      }
      if (v>max[j]) {
        max[j]=v;
      }
    }
  };
}
Example #2
0
Lib3dsSpotlightNode*
lib3ds_node_new_spotlight(Lib3dsLight *light) {
    Lib3dsNode *node;
    Lib3dsSpotlightNode *n;

    assert(light);
    node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT);
    strcpy(node->name, light->name);

    n = (Lib3dsSpotlightNode*)node;
    lib3ds_track_resize(&n->pos_track, 1);
    lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);

    lib3ds_track_resize(&n->color_track, 1);
    lib3ds_vector_copy(n->color_track.keys[0].value, light->color);

    lib3ds_track_resize(&n->hotspot_track, 1);
    n->hotspot_track.keys[0].value[0] = light->hotspot;

    lib3ds_track_resize(&n->falloff_track, 1);
    n->falloff_track.keys[0].value[0] = light->falloff;

    lib3ds_track_resize(&n->roll_track, 1);
    n->roll_track.keys[0].value[0] = light->roll;

    return n;
}
Example #3
0
/*!
 * \ingroup file
 */
void
lib3ds_file_bounding_box(Lib3dsFile *file, Lib3dsVector min, Lib3dsVector max)
{
    Lib3dsBool init=LIB3DS_FALSE;

    {
        Lib3dsVector lmin, lmax;
        Lib3dsMesh *p=file->meshes;

        if (!init && p) {
            init = LIB3DS_TRUE;
            lib3ds_mesh_bounding_box(p, min, max);
            p = p->next;
        }
        while (p) {
            lib3ds_mesh_bounding_box(p, lmin, lmax);
            lib3ds_vector_min(min, lmin);
            lib3ds_vector_max(max, lmax);
            p=p->next;
        }
    }
    {
        Lib3dsCamera *p=file->cameras;
        if (!init && p) {
            init = LIB3DS_TRUE;
            lib3ds_vector_copy(min, p->position);
            lib3ds_vector_copy(max, p->position);
        }

        while (p) {
            lib3ds_vector_min(min, p->position);
            lib3ds_vector_max(max, p->position);
            lib3ds_vector_min(min, p->target);
            lib3ds_vector_max(max, p->target);
            p=p->next;
        }
    }
    {
        Lib3dsLight *p=file->lights;
        if (!init && p) {
            init = LIB3DS_TRUE;
            lib3ds_vector_copy(min, p->position);
            lib3ds_vector_copy(max, p->position);
        }

        while (p) {
            lib3ds_vector_min(min, p->position);
            lib3ds_vector_max(max, p->position);
            if (p->spot_light) {
                lib3ds_vector_min(min, p->spot);
                lib3ds_vector_max(max, p->spot);
            }
            p=p->next;
        }
    }
}
Example #4
0
static void
rib_lights(FILE *o, Lib3dsFile *f, Lib3dsMatrix M)
{
  Lib3dsLight *light;
  Lib3dsNode *l;
  Lib3dsNode *s;
  int i=1;

  for (light=f->lights; light; light=light->next) {
    l=lib3ds_file_node_by_name(f, light->name, LIB3DS_LIGHT_NODE);
    s=lib3ds_file_node_by_name(f, light->name, LIB3DS_SPOT_NODE);
    if (!l) {
      fprintf(stderr, "***ERROR*** Invalid light!\n");
      exit(1);
    }
    if (s) {
      Lib3dsVector pos,spot;
      lib3ds_vector_copy(pos, l->data.light.pos);
      lib3ds_vector_copy(spot, s->data.spot.pos);
      fprintf(o,
        "LightSource "
        "\"lib3dslight\" "
        "%d "
        "\"string lighttype\" [\"spot\"] "
        "\"point from\" [%f %f %f] "
        "\"point to\" [%f %f %f]\n",
        i,
        pos[0],
        pos[1],
        pos[2],
        spot[0],
        spot[1],
        spot[2]
      );
    }
    else {
      Lib3dsVector pos;
      lib3ds_vector_copy(pos, l->data.light.pos);
      fprintf(o,
        "LightSource "
        "\"pointlight\" "
        "%d "
        "\"from\" [%f %f %f]\n",
        i,
        pos[0],
        pos[1],
        pos[2]
      );
    }
    fprintf(o, "Illuminate %d 1\n", i);
    ++i;
  }
}
Example #5
0
/*!
 * \ingroup tracks 
 */
void
lib3ds_lin3_track_eval(Lib3dsLin3Track *track, Lib3dsVector p, Lib3dsFloat t)
{
  Lib3dsLin3Key *k;
  Lib3dsFloat nt;
  Lib3dsFloat u;

  if (!track->keyL) {
    lib3ds_vector_zero(p);
    return;
  }
  if (!track->keyL->next) {
      lib3ds_vector_copy(p, track->keyL->value);
    return;
  }

  for (k=track->keyL; k->next!=0; k=k->next) {
    if ((t>=(Lib3dsFloat)k->tcb.frame) && (t<(Lib3dsFloat)k->next->tcb.frame)) {
      break;
    }
  }
  if (!k->next) {
    if (track->flags&LIB3DS_REPEAT) {
      nt=(Lib3dsFloat)fmod(t, k->tcb.frame);
      for (k=track->keyL; k->next!=0; k=k->next) {
        if ((nt>=(Lib3dsFloat)k->tcb.frame) && (nt<(Lib3dsFloat)k->next->tcb.frame)) {
          break;
        }
      }
      ASSERT(k->next);
    }
    else {
      lib3ds_vector_copy(p, k->value);
      return;
    }
  }
  else {
    nt=t;
  }
  u=nt - (Lib3dsFloat)k->tcb.frame;
  u/=(Lib3dsFloat)(k->next->tcb.frame - k->tcb.frame);
  
  lib3ds_vector_cubic(
    p,
    k->value,
    k->dd,
    k->next->ds,
    k->next->value,
    u
  );
}
Example #6
0
static void
mesh_dump(Lib3dsMesh *mesh) {
    int i;
    float p[3];

    assert(mesh);
    printf("  %s vertices=%ld faces=%ld\n",
           mesh->name,
           mesh->nvertices,
           mesh->nfaces);
    printf("  matrix:\n");
    matrix_dump(mesh->matrix);
    printf("  vertices (x, y, z, u, v):\n");
    for (i = 0; i < mesh->nvertices; ++i) {
        lib3ds_vector_copy(p, mesh->vertices[i]);
        printf("    %10.5f %10.5f %10.5f", p[0], p[1], p[2]);
        if (mesh->texcos) {
            printf("%10.5f %10.5f", mesh->texcos[i][0], mesh->texcos[i][1]);
        }
        printf("\n");
    }
    printf("  facelist:\n");
    for (i = 0; i < mesh->nfaces; ++i) {
        printf("    %4d %4d %4d  flags:%X  smoothing:%X  material:\"%d\"\n",
               mesh->faces[i].index[0],
               mesh->faces[i].index[1],
               mesh->faces[i].index[2],
               mesh->faces[i].flags,
               mesh->faces[i].smoothing_group,
               mesh->faces[i].material
              );
    }
}
Example #7
0
/*!
 * This function prints data associated with the specified mesh such as
 * vertex and point lists.
 *
 * \param mesh  Points to a mesh that you wish to view the data for.
 *
 * \return None
 *
 * \warning WIN32: Should only be used in a console window not in a GUI.
 *
 * \ingroup mesh
 */
void
lib3ds_mesh_dump(Lib3dsMesh *mesh)
{
  unsigned i;
  Lib3dsVector p;

  ASSERT(mesh);
  printf("  %s vertices=%ld faces=%ld\n",
    mesh->name,
    (long int)mesh->points,
    (long int)mesh->faces
  );
  printf("  matrix:\n");
  lib3ds_matrix_dump(mesh->matrix);
  printf("  point list:\n");
  for (i=0; i<mesh->points; ++i) {
    lib3ds_vector_copy(p, mesh->pointL[i].pos);
    printf ("    %8f %8f %8f\n", p[0], p[1], p[2]);
  }
  printf("  facelist:\n");
  for (i=0; i<mesh->faces; ++i) {
    printf ("    %4d %4d %4d  smoothing:%X  flags:%X  material:\"%s\"\n",
      mesh->faceL[i].points[0],
      mesh->faceL[i].points[1],
      mesh->faceL[i].points[2],
      (unsigned)mesh->faceL[i].smoothing,
      mesh->faceL[i].flags,
      mesh->faceL[i].material
    );
  }
}
Example #8
0
Lib3dsOmnilightNode*
lib3ds_node_new_omnilight(Lib3dsLight *light) {
    Lib3dsNode *node;
    Lib3dsOmnilightNode *n;

    assert(light);
    node = lib3ds_node_new(LIB3DS_NODE_OMNILIGHT);
    strcpy(node->name, light->name);

    n = (Lib3dsOmnilightNode*)node;
    lib3ds_track_resize(&n->pos_track, 1);
    lib3ds_vector_copy(n->pos_track.keys[0].value, light->position);

    lib3ds_track_resize(&n->color_track, 1);
    lib3ds_vector_copy(n->color_track.keys[0].value, light->color);

    return n;
}
Example #9
0
/*!
 * \ingroup tracks 
 */
void
lib3ds_lin3_key_setup(Lib3dsLin3Key *p, Lib3dsLin3Key *cp, Lib3dsLin3Key *c,
  Lib3dsLin3Key *cn, Lib3dsLin3Key *n)
{
  Lib3dsVector np,nn;
  Lib3dsFloat ksm,ksp,kdm,kdp;
  int i;
  
  ASSERT(c);
  if (!cp) {
    cp=c;
  }
  if (!cn) {
    cn=c;
  }
  if (!p && !n) {
    lib3ds_vector_zero(c->ds);
    lib3ds_vector_zero(c->dd);
    return;
  }

  if (n && p) {
    lib3ds_tcb(&p->tcb, &cp->tcb, &c->tcb, &cn->tcb, &n->tcb, &ksm, &ksp, &kdm, &kdp);
    lib3ds_vector_sub(np, c->value, p->value); 
    lib3ds_vector_sub(nn, n->value, c->value); 

    for(i=0; i<3; ++i) {
      c->ds[i]=ksm*np[i] + ksp*nn[i];
      c->dd[i]=kdm*np[i] + kdp*nn[i];
    }
  }
  else {
    if (p) {
      lib3ds_vector_sub(np, c->value, p->value);
      lib3ds_vector_copy(c->ds, np);
      lib3ds_vector_copy(c->dd, np);
    }
    if (n) {
      lib3ds_vector_sub(nn, n->value, c->value); 
      lib3ds_vector_copy(c->ds, nn);
      lib3ds_vector_copy(c->dd, nn);
    }
  }
}
Example #10
0
Lib3dsMeshInstanceNode*
lib3ds_node_new_mesh_instance(Lib3dsMesh *mesh, const char *instance_name, float pos0[3], float scl0[3], float rot0[4]) {
    Lib3dsNode *node;
    Lib3dsMeshInstanceNode *n;
    int i;

    node = lib3ds_node_new(LIB3DS_NODE_MESH_INSTANCE);
    if (mesh) {
        strcpy(node->name, mesh->name);
    } else {
        strcpy(node->name, "$$$DUMMY");
    }

    n = (Lib3dsMeshInstanceNode*)node;
    if (instance_name) {
        strcpy(n->instance_name, instance_name);
    }

    lib3ds_track_resize(&n->pos_track, 1);
    if (pos0) {
        lib3ds_vector_copy(n->pos_track.keys[0].value, pos0);
    }

    lib3ds_track_resize(&n->scl_track, 1);
    if (scl0) {
        lib3ds_vector_copy(n->scl_track.keys[0].value, scl0);
    } else {
        lib3ds_vector_make(n->scl_track.keys[0].value, 1, 1, 1);
    }

    lib3ds_track_resize(&n->rot_track, 1);
    if (rot0) {
        for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = rot0[i];
    } else {
        for (i = 0; i < 4; ++i) n->rot_track.keys[0].value[i] = 0;
    }

    return n;
}
Example #11
0
Lib3dsTargetNode*
lib3ds_node_new_spotligf_target(Lib3dsLight *light) {
    Lib3dsNode *node;
    Lib3dsTargetNode *n;

    assert(light);
    node = lib3ds_node_new(LIB3DS_NODE_SPOTLIGHT_TARGET);
    strcpy(node->name, light->name);

    n = (Lib3dsTargetNode*)node;
    lib3ds_track_resize(&n->pos_track, 1);
    lib3ds_vector_copy(n->pos_track.keys[0].value, light->target);

    return n;
}
Example #12
0
Lib3dsTargetNode*
lib3ds_node_new_camera_target(Lib3dsCamera *camera) {
    Lib3dsNode *node;
    Lib3dsTargetNode *n;

    assert(camera);
    node = lib3ds_node_new(LIB3DS_NODE_CAMERA_TARGET);
    strcpy(node->name, camera->name);

    n = (Lib3dsTargetNode*)node;
    lib3ds_track_resize(&n->pos_track, 1);
    lib3ds_vector_copy(n->pos_track.keys[0].value, camera->target);

    return n;
}
Example #13
0
Lib3dsAmbientColorNode*
lib3ds_node_new_ambient_color(float color0[3]) {
    Lib3dsNode *node;
    Lib3dsAmbientColorNode *n;

    node = lib3ds_node_new(LIB3DS_NODE_AMBIENT_COLOR);

    n = (Lib3dsAmbientColorNode*)node;
    lib3ds_track_resize(&n->color_track, 1);
    if (color0) {
        lib3ds_vector_copy(n->color_track.keys[0].value, color0);
    } else {
        lib3ds_vector_zero(n->color_track.keys[0].value);
    }

    return n;
}
Example #14
0
Lib3dsCameraNode*
lib3ds_node_new_camera(Lib3dsCamera *camera) {
    Lib3dsNode *node;
    Lib3dsCameraNode *n;

    assert(camera);
    node = lib3ds_node_new(LIB3DS_NODE_CAMERA);
    strcpy(node->name, camera->name);

    n = (Lib3dsCameraNode*)node;
    lib3ds_track_resize(&n->pos_track, 1);
    lib3ds_vector_copy(n->pos_track.keys[0].value, camera->position);

    lib3ds_track_resize(&n->fov_track, 1);
    n->fov_track.keys[0].value[0] = camera->fov;

    lib3ds_track_resize(&n->roll_track, 1);
    n->roll_track.keys[0].value[0] = camera->roll;

    return n;
}
Example #15
0
void write_mesh(FILE *o, Lib3dsFile *f, Lib3dsMeshInstanceNode *node) {
    float (*orig_vertices)[3];
    int export_texcos;
    int export_normals;
    int i, j;
    Lib3dsMesh *mesh;
        
    mesh = lib3ds_file_mesh_for_node(f, (Lib3dsNode*)node);
    if (!mesh || !mesh->vertices) return;

    fprintf(o, "# object %s\n", node->base.name);
    fprintf(o, "g %s\n", node->instance_name[0]? node->instance_name : node->base.name);

    orig_vertices = (float(*)[3])malloc(sizeof(float) * 3 * mesh->nvertices);
    memcpy(orig_vertices, mesh->vertices, sizeof(float) * 3 * mesh->nvertices);
     {
         float inv_matrix[4][4], M[4][4];
         float tmp[3];
         int i;
 
         lib3ds_matrix_copy(M, node->base.matrix);
         lib3ds_matrix_translate(M, -node->pivot[0], -node->pivot[1], -node->pivot[2]);
         lib3ds_matrix_copy(inv_matrix, mesh->matrix);
         lib3ds_matrix_inv(inv_matrix);
         lib3ds_matrix_mult(M, M, inv_matrix);
 
         for (i = 0; i < mesh->nvertices; ++i) {
             lib3ds_vector_transform(tmp, M, mesh->vertices[i]);
             lib3ds_vector_copy(mesh->vertices[i], tmp);
         }
     }

    export_texcos = (mesh->texcos != 0);
    export_normals = (mesh->faces != 0);

    for (i = 0; i < mesh->nvertices; ++i) {
        fprintf(o, "v %f %f %f\n", mesh->vertices[i][0], 
                                   mesh->vertices[i][1], 
                                   mesh->vertices[i][2]);
    }
    fprintf(o, "# %d vertices\n", mesh->nvertices);

    if (export_texcos) {
        for (i = 0; i < mesh->nvertices; ++i) {
            fprintf(o, "vt %f %f\n", mesh->texcos[i][0], 
                                     mesh->texcos[i][1]);
        }
        fprintf(o, "# %d texture vertices\n", mesh->nvertices);
    }

    if (export_normals) {
        float (*normals)[3] = (float(*)[3])malloc(sizeof(float) * 9 * mesh->nfaces);
        lib3ds_mesh_calculate_vertex_normals(mesh, normals);
        for (i = 0; i < 3 * mesh->nfaces; ++i) {
            fprintf(o, "vn %f %f %f\n", normals[i][0],
                                        normals[i][1],
                                        normals[i][2]);
        }
        free(normals);  
        fprintf(o, "# %d normals\n", 3 * mesh->nfaces);
    }

    {
        int mat_index = -1;
        for (i = 0; i < mesh->nfaces; ++i) {
            if (mat_index != mesh->faces[i].material) {
                mat_index = mesh->faces[i].material;
                if (mat_index != -1) {
                    fprintf(o, "usemtl %s\n", f->materials[mat_index]->name);
                }
            }

            fprintf(o, "f ");
            for (j = 0; j < 3; ++j) {
                fprintf(o, "%d", mesh->faces[i].index[j] + max_vertices + 1);
                if (export_texcos) {
                    fprintf(o, "/%d", mesh->faces[i].index[j] + max_texcos + 1);
                } else if (export_normals) {
                    fprintf(o, "/");
                }
                if (export_normals) {
                    fprintf(o, "/%d", 3 * i + j + max_normals + 1);
                }
                if (j < 3) {
                    fprintf(o, " ");
                }
            }
            fprintf(o, "\n");
        }
    }

    max_vertices += mesh->nvertices;
    if (export_texcos) 
        max_texcos += mesh->nvertices;
    if (export_normals) 
        max_normals += 3 * mesh->nfaces;
    
    memcpy(mesh->vertices, orig_vertices, sizeof(float) * 3 * mesh->nvertices);
    free(orig_vertices);
}
Example #16
0
/*!
 * \ingroup mesh
 */
Lib3dsBool
lib3ds_mesh_read(Lib3dsMesh *mesh, Lib3dsIo *io)
{
  Lib3dsChunk c;
  Lib3dsWord chunk;

  if (!lib3ds_chunk_read_start(&c, LIB3DS_N_TRI_OBJECT, io)) {
    return(LIB3DS_FALSE);
  }

  while ((chunk=lib3ds_chunk_read_next(&c, io))!=0) {
    switch (chunk) {
      case LIB3DS_MESH_MATRIX:
        {
          int i,j;
          
          lib3ds_matrix_identity(mesh->matrix);
          for (i=0; i<4; i++) {
            for (j=0; j<3; j++) {
              mesh->matrix[i][j]=lib3ds_io_read_float(io);
            }
          }
        }
        break;
      case LIB3DS_MESH_COLOR:
        {
          mesh->color=lib3ds_io_read_byte(io);
        }
        break;
      case LIB3DS_POINT_ARRAY:
        {
          unsigned i,j;
          unsigned points;
          
          lib3ds_mesh_free_point_list(mesh);
          points=lib3ds_io_read_word(io);
          if (points) {
            if (!lib3ds_mesh_new_point_list(mesh, points)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->points; ++i) {
              for (j=0; j<3; ++j) {
                mesh->pointL[i].pos[j]=lib3ds_io_read_float(io);
              }
            }
            ASSERT((!mesh->flags) || (mesh->points==mesh->flags));
            ASSERT((!mesh->texels) || (mesh->points==mesh->texels));
          }
        }
        break;
      case LIB3DS_POINT_FLAG_ARRAY:
        {
          unsigned i;
          unsigned flags;
          
          lib3ds_mesh_free_flag_list(mesh);
          flags=lib3ds_io_read_word(io);
          if (flags) {
            if (!lib3ds_mesh_new_flag_list(mesh, flags)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->flags; ++i) {
              mesh->flagL[i]=lib3ds_io_read_word(io);
            }
            ASSERT((!mesh->points) || (mesh->flags==mesh->points));
            ASSERT((!mesh->texels) || (mesh->flags==mesh->texels));
          }
        }
        break;
      case LIB3DS_FACE_ARRAY:
        {
          lib3ds_chunk_read_reset(&c, io);
          if (!face_array_read(mesh, io)) {
            return(LIB3DS_FALSE);
          }
        }
        break;
      case LIB3DS_MESH_TEXTURE_INFO:
        {
          int i,j;

          for (i=0; i<2; ++i) {
            mesh->map_data.tile[i]=lib3ds_io_read_float(io);
          }
          for (i=0; i<3; ++i) {
            mesh->map_data.pos[i]=lib3ds_io_read_float(io);
          }
          mesh->map_data.scale=lib3ds_io_read_float(io);

          lib3ds_matrix_identity(mesh->map_data.matrix);
          for (i=0; i<4; i++) {
            for (j=0; j<3; j++) {
              mesh->map_data.matrix[i][j]=lib3ds_io_read_float(io);
            }
          }
          for (i=0; i<2; ++i) {
            mesh->map_data.planar_size[i]=lib3ds_io_read_float(io);
          }
          mesh->map_data.cylinder_height=lib3ds_io_read_float(io);
        }
        break;
      case LIB3DS_TEX_VERTS:
        {
          unsigned i;
          unsigned texels;
          
          lib3ds_mesh_free_texel_list(mesh);
          texels=lib3ds_io_read_word(io);
          if (texels) {
            if (!lib3ds_mesh_new_texel_list(mesh, texels)) {
              LIB3DS_ERROR_LOG;
              return(LIB3DS_FALSE);
            }
            for (i=0; i<mesh->texels; ++i) {
              mesh->texelL[i][0]=lib3ds_io_read_float(io);
              mesh->texelL[i][1]=lib3ds_io_read_float(io);
            }
            ASSERT((!mesh->points) || (mesh->texels==mesh->points));
            ASSERT((!mesh->flags) || (mesh->texels==mesh->flags));
          }
        }
        break;
      default:
        lib3ds_chunk_unknown(chunk);
    }
  }
  {
    unsigned j;

    for (j=0; j<mesh->faces; ++j) {
      ASSERT(mesh->faceL[j].points[0]<mesh->points);
      ASSERT(mesh->faceL[j].points[1]<mesh->points);
      ASSERT(mesh->faceL[j].points[2]<mesh->points);
      lib3ds_vector_normal(
        mesh->faceL[j].normal,
        mesh->pointL[mesh->faceL[j].points[0]].pos,
        mesh->pointL[mesh->faceL[j].points[1]].pos,
        mesh->pointL[mesh->faceL[j].points[2]].pos
      );
    }
  }

  if (lib3ds_matrix_det(mesh->matrix) < 0.0)
  {
    /* Flip X coordinate of vertices if mesh matrix 
       has negative determinant */
    Lib3dsMatrix inv_matrix, M;
    Lib3dsVector tmp;
    unsigned i;

    lib3ds_matrix_copy(inv_matrix, mesh->matrix);
    lib3ds_matrix_inv(inv_matrix);

    lib3ds_matrix_copy(M, mesh->matrix);
    lib3ds_matrix_scale_xyz(M, -1.0f, 1.0f, 1.0f);
    lib3ds_matrix_mult(M, inv_matrix);

    for (i=0; i<mesh->points; ++i) {
      lib3ds_vector_transform(tmp, M, mesh->pointL[i].pos);
      lib3ds_vector_copy(mesh->pointL[i].pos, tmp);
    }
  }

  lib3ds_chunk_read_end(&c, io);

  return(LIB3DS_TRUE);
}
Example #17
0
void dump_wzm_file(Lib3dsFile *f, FILE *ctl, bool swapYZ, bool invertUV, bool reverseWinding, unsigned int baseTexFlags, float scaleFactor)
{
	Lib3dsMesh *m;
	Lib3dsMaterial *material;
	int meshIdx, j;

	fprintf(ctl, "WZM 1\n");

	for (j = 0, material = f->materials; material; material = material->next, j++)
	{
		Lib3dsTextureMap *texture = &material->texture1_map;

		resToLower(texture->name);
		if (j > 0)
		{
			fprintf(stderr, "Texture %d %s: More than one texture currently not supported!\n", j, texture->name);
			continue;
		}
		fprintf(ctl, "TEXTURE %s\n", texture->name);
	}

	for (j = 0, m = f->meshes; m; m = m->next, j++);
	fprintf(ctl, "MESHES %d\n", j);

	for (meshIdx = 0, m = f->meshes; m; m = m->next, meshIdx++)
	{
		unsigned int i;

		fprintf(ctl, "MESH %d\n", meshIdx);
		fprintf(ctl, "TEAMCOLOURS 0\n");
		fprintf(ctl, "VERTICES %d\n", m->points);
		fprintf(ctl, "FACES %d\n", m->faces);
		fprintf(ctl, "VERTEXARRAY\n");
		for (i = 0; i < m->points; i++)
		{
			Lib3dsVector pos;

			lib3ds_vector_copy(pos, m->pointL[i].pos);

			if (swapYZ)
			{
				fprintf(ctl, "\t%f %f %f\n", pos[0] * scaleFactor, pos[2] * scaleFactor, pos[1] * scaleFactor);
			}
			else
			{
				fprintf(ctl, "\t%f %f %f\n", pos[0] * scaleFactor, pos[1] * scaleFactor, pos[2] * scaleFactor);
			}
		}

		fprintf(ctl, "TEXTUREARRAYS 1\n");
		fprintf(ctl, "TEXTUREARRAY 0\n");
		for (i = 0; i < m->points; i++)
		{
			if (invertUV)
			{
				fprintf(ctl, "\t%f %f\n", m->texelL[i][0], 1.0f - m->texelL[i][1]);
			}
			else
			{
				fprintf(ctl, "\t%f %f\n", m->texelL[i][0], m->texelL[i][1]);
			}
		}

		fprintf(ctl, "INDEXARRAY\n");
		for (i = 0; i < m->faces; ++i)
		{
			Lib3dsFace *face = &m->faceL[i];

			if (reverseWinding)
			{
				fprintf(ctl, "\t%d %d %d\n", (int)face->points[2], (int)face->points[1], (int)face->points[0]);
			}
			else
			{
				fprintf(ctl, "\t%d %d %d\n", (int)face->points[0], (int)face->points[1], (int)face->points[2]);
			}
		}
		fprintf(ctl, "FRAMES 0\n");
		fprintf(ctl, "CONNECTORS 0\n");
	}
}
Example #18
0
/*!
 * Calculates the vertex normals corresponding to the smoothing group
 * settings for each face of a mesh.
 *
 * \param mesh      A pointer to the mesh to calculate the normals for.
 * \param normalL   A pointer to a buffer to store the calculated
 *                  normals. The buffer must have the size:
 *                  3*sizeof(Lib3dsVector)*mesh->faces. 
 *
 * To allocate the normal buffer do for example the following:
 * \code
 *  Lib3dsVector *normalL = malloc(3*sizeof(Lib3dsVector)*mesh->faces);
 * \endcode
 *
 * To access the normal of the i-th vertex of the j-th face do the 
 * following:
 * \code
 *   normalL[3*j+i]
 * \endcode
 *
 * \ingroup mesh
 */
void
lib3ds_mesh_calculate_normals(Lib3dsMesh *mesh, Lib3dsVector *normalL)
{
  Lib3dsFaces **fl; 
  Lib3dsFaces *fa; 
  unsigned i,j,k;

  if (!mesh->faces) {
    return;
  }

  fl=calloc(sizeof(Lib3dsFaces*),mesh->points);
  ASSERT(fl);
  fa=calloc(sizeof(Lib3dsFaces),3*mesh->faces);
  ASSERT(fa);
  k=0;
  for (i=0; i<mesh->faces; ++i) {
    Lib3dsFace *f=&mesh->faceL[i];
    for (j=0; j<3; ++j) {
      Lib3dsFaces* l=&fa[k++];
      ASSERT(f->points[j]<mesh->points);
      l->face=f;
      l->next=fl[f->points[j]];
      fl[f->points[j]]=l;
    }
  }
  
  for (i=0; i<mesh->faces; ++i) {
    Lib3dsFace *f=&mesh->faceL[i];
    for (j=0; j<3; ++j) {
      // FIXME: static array needs at least check!!
      Lib3dsVector n,N[128];
      Lib3dsFaces *p;
      int k,l;
      int found;

      ASSERT(f->points[j]<mesh->points);

      if (f->smoothing) {
        lib3ds_vector_zero(n);
        k=0;
        for (p=fl[f->points[j]]; p; p=p->next) {
          found=0;
          for (l=0; l<k; ++l) {
	    if( l >= 128 )
	      printf("array N overflow: i=%d, j=%d, k=%d\n", i,j,k);
            if (fabs(lib3ds_vector_dot(N[l], p->face->normal)-1.0)<1e-5) {
              found=1;
              break;
            }
          }
          if (!found) {
            if (f->smoothing & p->face->smoothing) {
              lib3ds_vector_add(n,n, p->face->normal);
              lib3ds_vector_copy(N[k], p->face->normal);
              ++k;
            }
          }
        }
      } 
      else {
        lib3ds_vector_copy(n, f->normal);
      }
      lib3ds_vector_normalize(n);

      lib3ds_vector_copy(normalL[3*i+j], n);
    }
  }

  free(fa);
  free(fl);
}
Example #19
0
int main(int argc, char **argv) {
    Lib3dsFile *file = lib3ds_file_new();
    file->frames = 360;
    
    {
        Lib3dsMaterial *mat = lib3ds_material_new("c_tex");
        lib3ds_file_insert_material(file, mat, -1);
        strcpy(mat->texture1_map.name, "cube.tga");
        mat->texture1_map.percent = 1.0;

        mat = lib3ds_material_new("c_red");
        lib3ds_file_insert_material(file, mat, -1);
        mat->diffuse[0] = 1.0;
        mat->diffuse[1] = 0.0;
        mat->diffuse[2] = 0.0;

        mat = lib3ds_material_new("c_blue");
        lib3ds_file_insert_material(file, mat, -1);
        mat->diffuse[0] = 0.0;
        mat->diffuse[1] = 0.0;
        mat->diffuse[2] = 1.0;
    }

    {
        int i, j;
        Lib3dsMesh *mesh = lib3ds_mesh_new("cube");
        Lib3dsMeshInstanceNode *inst;        
        lib3ds_file_insert_mesh(file, mesh, -1);

        lib3ds_mesh_resize_vertices(mesh, 8, 1, 0);
        for (i = 0; i < 8; ++i) {
            lib3ds_vector_copy(mesh->vertices[i], g_vertices[i]);
            mesh->texcos[i][0] = g_texcoords[i][0];
            mesh->texcos[i][1] = g_texcoords[i][1];
        }

        lib3ds_mesh_resize_faces(mesh, 12);
        for (i = 0; i < 12; ++i) {
            for (j = 0; j < 3; ++j) {
                mesh->faces[i].index[j] = g_indices[i][j];
            }
        }

        for (i = 0; i < 8; ++i) {
            mesh->faces[i].material = 0;
        }
        for (i = 0; i < 2; ++i) {
            mesh->faces[8+i].material = 1;
        }
        for (i = 0; i < 2; ++i) {
            mesh->faces[10+i].material = 2;
        }

        inst = lib3ds_node_new_mesh_instance(mesh, "01", NULL, NULL, NULL);
        lib3ds_file_append_node(file, (Lib3dsNode*)inst, NULL);
    }

    {
        Lib3dsCamera *camera;
        Lib3dsCameraNode *n;
        Lib3dsTargetNode *t;
        int i;

        camera = lib3ds_camera_new("camera01");
        lib3ds_file_insert_camera(file, camera, -1);
        lib3ds_vector_make(camera->position, 0.0, -100, 0.0);
        lib3ds_vector_make(camera->target, 0.0, 0.0, 0.0);

        n = lib3ds_node_new_camera(camera);
        t = lib3ds_node_new_camera_target(camera);
        lib3ds_file_append_node(file, (Lib3dsNode*)n, NULL);
        lib3ds_file_append_node(file, (Lib3dsNode*)t, NULL);

        lib3ds_track_resize(&n->pos_track, 37);
        for (i = 0; i <= 36; i++) {
            n->pos_track.keys[i].frame = 10 * i;
            lib3ds_vector_make(n->pos_track.keys[i].value, 
                (float)(100.0 * cos(2 * M_PI * i / 36.0)), 
                (float)(100.0 * sin(2 * M_PI * i / 36.0)), 
                50.0
            );
        }
    }

    if (!lib3ds_file_save(file, "cube.3ds")) {
        fprintf(stderr, "ERROR: Saving 3ds file failed!\n");
    }
    lib3ds_file_free(file);
}
Example #20
0
static void dump_to_3ds(Lib3dsFile *f, FILE *fp)
{
	Lib3dsMesh	*m = lib3ds_mesh_new("Warzone Mesh");
	Lib3dsMaterial	*material = lib3ds_material_new("Warzone texture");
	Lib3dsTextureMap *texture = &material->texture1_map;
	int i, num, x, y, levels;
	char s[200];

	num = fscanf(fp, "PIE %d\n", &i);
	if (num != 1)
	{
		fprintf(stderr, "Bad PIE file %s\n", input);
		exit(1);
	}
	fprintf(stdout, "PIE version %d\n", i);

	num = fscanf(fp, "TYPE %d\n", &i); // ignore
	if (num != 1)
	{
		fprintf(stderr, "Bad TYPE directive in %s\n", input);
		exit(1);
	}

	num = fscanf(fp, "TEXTURE %d %s %d %d\n", &i, s, &x, &y);
	if (num != 4)
	{
		fprintf(stderr, "Bad TEXTURE directive in %s\n", input);
		exit(1);
	}
	strcpy(texture->name, s);

	num = fscanf(fp, "LEVELS %d\n", &levels);
	if (num != 1)
	{
		fprintf(stderr, "Bad LEVELS directive in %s\n", input);
		exit(1);
	}

	f->frames = levels;
	f->meshes = m;
	f->materials = material;
	for (i = 0; i < levels; i++)
	{
		int j, points, faces, faces3DS, faceCount, points3DS, pointCount;
		WZ_FACE *faceList;
		WZ_POSITION *posList;

		num = fscanf(fp, "LEVEL %d\n", &x);
		if (num != 1 || (i + 1) != x)
		{
			fprintf(stderr, "Bad LEVEL directive in %s, was %d should be %d\n", input, x, i + 1);
			exit(1);
		}

		num = fscanf(fp, "POINTS %d\n", &points);
		if (num != 1)
		{
			fprintf(stderr, "Bad POINTS directive in %s frame %d\n", input, i);
			exit(1);
		}
		posList = malloc(sizeof(WZ_POSITION) * points);
		for (j = 0; j < points; j++)
		{
			if (swapYZ)
			{
				num = fscanf(fp, "%d %d %d\n", &posList[j].x, &posList[j].z, &posList[j].y);
			}
			else
			{
				num = fscanf(fp, "%d %d %d\n", &posList[j].x, &posList[j].y, &posList[j].z);
			}
			if (num != 3)
			{
				fprintf(stderr, "Bad POINTS entry frame %d, number %d\n", i, j);
				exit(1);
			}
		}

		num = fscanf(fp, "POLYGONS %d", &faces);
		if (num != 1)
		{
			fprintf(stderr, "Bad POLYGONS directive in %s frame %d\n", input, i);
			exit(1);			
		}
		faces3DS = faces;	// for starters
		faceList = malloc(sizeof(WZ_FACE) * faces);
		points3DS = 0;
		for (j = 0; j < faces; ++j)
		{
			int k;
			unsigned int flags;

			num = fscanf(fp, "\n%x", &flags);
			if (num != 1)
			{
				fprintf(stderr, "Bad POLYGONS texture flag entry frame %d, number %d\n", i, j);
				exit(1);
			}
			if (!(flags & iV_IMD_TEX))
			{
				fprintf(stderr, "Bad texture flag entry frame %d, number %d - no texture flag!\n", i, j);
				exit(1);
			}

			num = fscanf(fp, "%d", &faceList[j].vertices);
			if (num != 1)
			{
				fprintf(stderr, "Bad POLYGONS vertices entry frame %d, number %d\n", i, j);
				exit(1);
			}
			assert(faceList[j].vertices <= MAX_POLYGON_SIZE); // larger polygons not supported
			assert(faceList[j].vertices >= 3); // points and lines not supported
			if (faceList[j].vertices > 3)
			{
				// since they are triangle fans already, we get to do easy tessellation
				faces3DS += (faceList[j].vertices - 3);
			}
			points3DS += faceList[j].vertices;

			// Read in vertex indices and texture coordinates
			for (k = 0; k < faceList[j].vertices; k++)
			{
				num = fscanf(fp, "%d", &faceList[j].index[k]);
				if (num != 1)
				{
					fprintf(stderr, "Bad vertex position entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
			if (flags & iV_IMD_TEXANIM)
			{
				// read in and discard animation values for now
				int frames, rate, width, height;

				num = fscanf(fp, "%d %d %d %d", &frames, &rate, &width, &height);
				if (num != 4)
				{
					fprintf(stderr, "Bad texture animation entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
			for (k = 0; k < faceList[j].vertices; k++)
			{
				num = fscanf(fp, "%d %d", &faceList[j].texCoord[k][0], &faceList[j].texCoord[k][1]);
				if (num != 2)
				{
					fprintf(stderr, "Bad texture coordinate entry frame %d, number %d\n", i, j);
					exit(1);
				}
			}
		}

		// Calculate position list. Since positions hold texture coordinates in 3DS, unlike in Warzone,
		// we need to use some black magic to transfer them over here.
		lib3ds_mesh_new_point_list(m, points3DS);
		lib3ds_mesh_new_texel_list(m, points3DS);
		pointCount = 0;
		for (j = 0; j < faces; j++)
		{
			int k;

			for (k = 0; k < faceList[j].vertices; k++)
			{
				Lib3dsVector pos;

				pos[0] = posList[faceList[j].index[k]].x;
				pos[1] = posList[faceList[j].index[k]].y;
				pos[2] = posList[faceList[j].index[k]].z;

				lib3ds_vector_copy(m->pointL[pointCount].pos, pos);
				faceList[j].index[k] = pointCount; // use new position list

				if (invertUV)
				{
					m->texelL[pointCount][0] = ((float)faceList[j].texCoord[k][0] / 256.0f);
					m->texelL[pointCount][1] = 1.0f - ((float)faceList[j].texCoord[k][1] / 256.0f);
				}
				else
				{
					m->texelL[pointCount][0] = ((float)faceList[j].texCoord[k][0] / 256.0f);
					m->texelL[pointCount][1] = ((float)faceList[j].texCoord[k][1] / 256.0f);
				}
				pointCount++;
			}
		}

		lib3ds_mesh_new_face_list(m, faces3DS);
		faceCount = 0;

		// TODO reverse winding afterwards
		for (j = 0; j < faces; j++)
		{
			int k, key, previous;

			key = m->faceL[faceCount].points[0] = faceList[j].index[0];
			m->faceL[faceCount].points[1] = faceList[j].index[1];
			previous = m->faceL[faceCount].points[2] = faceList[j].index[2];
			faceCount++;

			// Generate triangles from the Warzone triangle fans (PIEs, get it?)
			for (k = 3; k < faceList[j].vertices; k++)
			{
				m->faceL[faceCount].points[0] = key;
				m->faceL[faceCount].points[1] = previous;
				previous = m->faceL[faceCount].points[0] = faceList[j].index[k];
			}

			// Since texture coordinates are properties of positions, not indices,
			// we do not need a similar expansion of these
		}
		free(faceList);
		free(posList);
	}
	if (!lib3ds_file_save(f, output))
	{
		fprintf(stderr, "Cannot open \"%s\" for writing: %s", output, strerror(errno));
		exit(1);
	}
}
Example #21
0
/*!
* Render node recursively, first children, then parent.
* Each node receives its own OpenGL display list.
*/
static void
render_node(Lib3dsNode *node) {
	assert(file);
	
	
	{
		Lib3dsNode *p;
		for (p = node->childs; p != 0; p = p->next) {
			render_node(p);
		}
	}
	if (node->type == LIB3DS_NODE_MESH_INSTANCE) {
		int index;
		Lib3dsMesh *mesh;
		Lib3dsMeshInstanceNode *n = (Lib3dsMeshInstanceNode*)node;
		
		
		if (strcmp(node->name, "$$$DUMMY") == 0) {
			return;
		}
		
		
		index = lib3ds_file_mesh_by_name(file, n->instance_name);
		if (index < 0)
			index = lib3ds_file_mesh_by_name(file, node->name);
		if (index < 0) {
			return;
		}
		mesh = file->meshes[index];
		
		
		if (!mesh->user_id) {
			assert(mesh);
			
			
			mesh->user_id = glGenLists(1);
			glNewList(mesh->user_id, GL_COMPILE);
			
			
			{
				int p;
				float (*normalL)[3] = (float(*)[3])malloc(3 * 3 * sizeof(float) * mesh->nfaces);
				Lib3dsMaterial *oldmat = (Lib3dsMaterial *) - 1;
				{
					float M[4][4];
					lib3ds_matrix_copy(M, mesh->matrix);
					lib3ds_matrix_inv(M);
					glMultMatrixf(&M[0][0]);
				}
				lib3ds_mesh_calculate_vertex_normals(mesh, normalL);
				
				
				for (p = 0; p < mesh->nfaces; ++p) {
					Lib3dsMaterial *mat = 0;
#ifdef USE_SDL
					Player_texture *pt = NULL;
					int tex_mode = 0;
#endif
					if (mesh->faces[p].material > 0) {
						mat = file->materials[mesh->faces[p].material];
					}
					
					
					if (mat != oldmat) {
						if (mat) {
							if (mat->two_sided)
								glDisable(GL_CULL_FACE);
							else
								glEnable(GL_CULL_FACE);
							
							
							glDisable(GL_CULL_FACE);
							
							
							/* Texturing added by Gernot < *****@*****.** > */
							
							
							if (mat->texture1_map.name[0]) { /* texture map? */
								Lib3dsTextureMap *tex = &mat->texture1_map;
								if (!tex->user_ptr) { /* no player texture yet? */
									char texname[1024];
									pt = (Player_texture*)malloc(sizeof(*pt));
									tex->user_ptr = pt;
									//snprintf(texname, sizeof(texname), "%s/%s", datapath, tex->name);
									strcpy(texname, datapath);
									strcat(texname, "/");
									strcat(texname, tex->name);
#ifdef DEBUG
									printf("Loading texture map, name %s\n", texname);
#endif /* DEBUG */
#ifdef USE_SDL
#ifdef USE_SDL_IMG_load
									pt->bitmap = IMG_load(texname);
#else
									pt->bitmap = IMG_Load(texname);
#endif /* IMG_Load */
									
									
#else /* USE_SDL */
									pt->bitmap = NULL;
									fputs("3dsplayer: Warning: No image loading support, skipping texture.\n", stderr);
#endif /* USE_SDL */
									if (pt->bitmap) { /* could image be loaded ? */
																		/* this OpenGL texupload code is incomplete format-wise!
																		* to make it complete, examine SDL_surface->format and
																		* tell us @lib3ds.sf.net about your improvements :-)
										*/
										int upload_format = GL_RED; /* safe choice, shows errors */
#ifdef USE_SDL
										int bytespp = pt->bitmap->format->BytesPerPixel;
										void *pixel = NULL;
										glGenTextures(1, &pt->tex_id);
#ifdef DEBUG
										printf("Uploading texture to OpenGL, id %d, at %d bytepp\n",
											pt->tex_id, bytespp);
#endif /* DEBUG */
										if (pt->bitmap->format->palette) {
											pixel = convert_to_RGB_Surface(pt->bitmap);
											upload_format = GL_RGBA;
										} else {
											pixel = pt->bitmap->pixels;
											/* e.g. this could also be a color palette */
											if (bytespp == 1) upload_format = GL_LUMINANCE;
											else if (bytespp == 3) upload_format = GL_RGB;
											else if (bytespp == 4) upload_format = GL_RGBA;
										}
										glBindTexture(GL_TEXTURE_2D, pt->tex_id);
										glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
											TEX_XSIZE, TEX_YSIZE, 0,
											GL_RGBA, GL_UNSIGNED_BYTE, NULL);
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
										glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
										glTexParameteri(GL_TEXTURE_2D,
											GL_TEXTURE_MAG_FILTER, GL_LINEAR);
										glTexParameteri(GL_TEXTURE_2D,
											GL_TEXTURE_MIN_FILTER, GL_LINEAR);
										glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
										glTexSubImage2D(GL_TEXTURE_2D,
											0, 0, 0, pt->bitmap->w, pt->bitmap->h,
											upload_format, GL_UNSIGNED_BYTE, pixel);
										pt->scale_x = (float)pt->bitmap->w / (float)TEX_XSIZE;
										pt->scale_y = (float)pt->bitmap->h / (float)TEX_YSIZE;
#endif /* USE_SDL */
										pt->valid = 1;
									} else {
										fprintf(stderr,
											"Load of texture %s did not succeed "
											"(format not supported !)\n",
											texname);
										pt->valid = 0;
									}
								} else {
									pt = (Player_texture *)tex->user_ptr;
								}
								tex_mode = pt->valid;
							} else {
								tex_mode = 0;
							}
							
							
							{
								float a[4], d[4], s[4];
								int i;
								for (i=0; i<3; ++i) {
									a[i] = mat->ambient[i];
									d[i] = mat->diffuse[i];
									s[i] = mat->specular[i];
								}
								a[3] = d[3] = s[3] = 1.0f;
								
								glMaterialfv(GL_FRONT, GL_AMBIENT, a);
								glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
								glMaterialfv(GL_FRONT, GL_SPECULAR, s);
							}
							glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*mat->shininess));
 } else {
	 static const float a[4] = {0.7, 0.7, 0.7, 1.0};
	 static const float d[4] = {0.7, 0.7, 0.7, 1.0};
	 static const float s[4] = {1.0, 1.0, 1.0, 1.0};
	 glMaterialfv(GL_FRONT, GL_AMBIENT, a);
	 glMaterialfv(GL_FRONT, GL_DIFFUSE, d);
	 glMaterialfv(GL_FRONT, GL_SPECULAR, s);
	 glMaterialf(GL_FRONT, GL_SHININESS, pow(2, 10.0*0.5));
 }
 oldmat = mat;
 }
 
 
 else if (mat != NULL && mat->texture1_map.name[0]) {
	 Lib3dsTextureMap *tex = &mat->texture1_map;
	 if (tex != NULL && tex->user_ptr != NULL) {
		 pt = (Player_texture *)tex->user_ptr;
		 tex_mode = pt->valid;
	 }
 }
 
 
 
 
 {
	 int i;
	 
#ifndef USE_GL10
	 if (tex_mode) {
		 //printf("Binding texture %d\n", pt->tex_id);
		 glEnable(GL_TEXTURE_2D);
		 glBindTexture(GL_TEXTURE_2D, pt->tex_id);
	 }
#endif	 
	 
#if 0
	 {
		 float v1[3], n[3], v2[3];
		 glBegin(GL_LINES);
		 for (i = 0; i < 3; ++i) {
			 lib3ds_vector_copy(v1, mesh->vertices[f->points[i]]);
			 glVertex3fv(v1);
			 lib3ds_vector_copy(n, normalL[3*p+i]);
			 lib3ds_vector_scalar(n, 10.f);
			 lib3ds_vector_add(v2, v1, n);
			 glVertex3fv(v2);
		 }
		 glEnd();
	 }
#endif
	 
	 
	 glBegin(GL_TRIANGLES);
	 for (i = 0; i < 3; ++i) {
		 glNormal3fv(normalL[3*p+i]);
		 
		 
		 if (tex_mode) {
			 glTexCoord2f(
				 mesh->texcos[mesh->faces[p].index[i]][1]*pt->scale_x,
				 pt->scale_y - mesh->texcos[mesh->faces[p].index[i]][0]*pt->scale_y);
		 }
		 
		 
		 glVertex3fv(mesh->vertices[mesh->faces[p].index[i]]);
	 }
	 glEnd();
	 
	 
	 if (tex_mode)
		 glDisable(GL_TEXTURE_2D);
 }
 }
 
 
 free(normalL);
 }
 
 
 glEndList();
 }
 
 
 if (mesh->user_id) {
	 glPushMatrix();
	 glMultMatrixf(&node->matrix[0][0]);
	 glTranslatef(-n->pivot[0], -n->pivot[1], -n->pivot[2]);
	 glCallList(mesh->user_id);
	 /* glutSolidSphere(50.0, 20,20); */
	 glPopMatrix();
	 if (flush)
		 glFlush();
 }
 }
}
Example #22
0
/*!
 * Calculates the vertex normals corresponding to the smoothing group
 * settings for each face of a mesh.
 *
 * \param mesh      A pointer to the mesh to calculate the normals for.
 * \param normals   A pointer to a buffer to store the calculated
 *                  normals. The buffer must have the size:
 *                  3*3*sizeof(float)*mesh->nfaces.
 *
 * To allocate the normal buffer do for example the following:
 * \code
 *  Lib3dsVector *normals = malloc(3*3*sizeof(float)*mesh->nfaces);
 * \endcode
 *
 * To access the normal of the i-th vertex of the j-th face do the
 * following:
 * \code
 *   normals[3*j+i]
 * \endcode
 */
void
lib3ds_mesh_calculate_vertex_normals(Lib3dsMesh *mesh, float (*normals)[3]) {
    Lib3dsFaces **fl;
    Lib3dsFaces *fa;
    int i, j;

    if (!mesh->nfaces) {
        return;
    }

    fl = (Lib3dsFaces**)calloc(sizeof(Lib3dsFaces*), mesh->nvertices);
    fa = (Lib3dsFaces*)malloc(sizeof(Lib3dsFaces) * 3 * mesh->nfaces);

    for (i = 0; i < mesh->nfaces; ++i) {
        for (j = 0; j < 3; ++j) {
            Lib3dsFaces* l = &fa[3*i+j];
            float p[3], q[3], n[3];
            float len, weight;

            l->index = i;
            l->next = fl[mesh->faces[i].index[j]];
            fl[mesh->faces[i].index[j]] = l;

            lib3ds_vector_sub(p, mesh->vertices[mesh->faces[i].index[j<2? j + 1 : 0]], mesh->vertices[mesh->faces[i].index[j]]);
            lib3ds_vector_sub(q, mesh->vertices[mesh->faces[i].index[j>0? j - 1 : 2]], mesh->vertices[mesh->faces[i].index[j]]);
            lib3ds_vector_cross(n, p, q);
            len = lib3ds_vector_length(n);
            if (len > 0) {
                weight = (float)atan2(len, lib3ds_vector_dot(p, q));
                lib3ds_vector_scalar_mul(l->normal, n, weight / len);
            } else {
                lib3ds_vector_zero(l->normal);
            }
        }
    }

    for (i = 0; i < mesh->nfaces; ++i) {
        Lib3dsFace *f = &mesh->faces[i];
        for (j = 0; j < 3; ++j) {
            float n[3];
            Lib3dsFaces *p;
            Lib3dsFace *pf;

            assert(mesh->faces[i].index[j] < mesh->nvertices);

            if (f->smoothing_group) {
                unsigned smoothing_group = f->smoothing_group;

                lib3ds_vector_zero(n);
                for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) {
                    pf = &mesh->faces[p->index];
                    if (pf->smoothing_group & f->smoothing_group)
                        smoothing_group |= pf->smoothing_group;
                }

                for (p = fl[mesh->faces[i].index[j]]; p; p = p->next) {
                    pf = &mesh->faces[p->index];
                    if (smoothing_group & pf->smoothing_group) {
                        lib3ds_vector_add(n, n, p->normal);
                    }
                }
            } else {
                lib3ds_vector_copy(n, fa[3*i+j].normal);
            }

            lib3ds_vector_normalize(n);
            lib3ds_vector_copy(normals[3*i+j], n);
        }
    }

    free(fa);
    free(fl);
}
Example #23
0
MODEL *QWzmViewer::load3DS(QString input)
{
	const bool swapYZ = true;
	const bool reverseWinding = true;
	const bool invertUV = true;
	const float scaleFactor = 1.0f;
	Lib3dsFile *f = lib3ds_file_load(input.toAscii().constData());
	Lib3dsMaterial *material = f->materials;
	int meshes = 0;
	Lib3dsMesh *m;
	int meshIdx;
	MODEL *psModel;

	if (!f)
	{
		qWarning("Loading 3DS file %s failed", input.toAscii().constData());
		return NULL;
	}

	for (meshes = 0, m = f->meshes; m; m = m->next, meshes++) ;	// count the meshes

	psModel = createModel(meshes, 0);
	if (!psModel)
	{
		qFatal("Out of memory");
	}

	// Grab texture name
	for (int j = 0; material; material = material->next, j++)
	{
		Lib3dsTextureMap *texture = &material->texture1_map;
		QString texName(texture->name);

		if (j > 0)
		{
			qWarning("Texture %d %s: More than one texture currently not supported!", j, texture->name);
			continue;
		}
		strcpy(psModel->texPath, texName.toLower().toAscii().constData());
	}

	// Grab each mesh
	for (meshIdx = 0, m = f->meshes; m; m = m->next, meshIdx++)
	{
		MESH *psMesh = &psModel->mesh[meshIdx];

		psMesh->vertices = m->points;
		psMesh->faces = m->faces;
		psMesh->vertexArray = (GLfloat*)malloc(sizeof(GLfloat) * psMesh->vertices * 3);
		psMesh->indexArray = (GLuint*)malloc(sizeof(GLuint) * psMesh->faces * 3);
		psMesh->textureArrays = 1;	// only one supported from 3DS
		psMesh->textureArray[0] = (GLfloat*)malloc(sizeof(GLfloat) * psMesh->vertices * 2);

		for (unsigned int i = 0; i < m->points; i++)
		{
			Lib3dsVector pos;

			lib3ds_vector_copy(pos, m->pointL[i].pos);

			if (swapYZ)
			{
				psMesh->vertexArray[i * 3 + 0] = pos[0] * scaleFactor;
				psMesh->vertexArray[i * 3 + 1] = pos[2] * scaleFactor;
				psMesh->vertexArray[i * 3 + 2] = pos[1] * scaleFactor;
			}
			else
			{
				psMesh->vertexArray[i * 3 + 0] = pos[0] * scaleFactor;
				psMesh->vertexArray[i * 3 + 1] = pos[1] * scaleFactor;
				psMesh->vertexArray[i * 3 + 2] = pos[2] * scaleFactor;
			}
		}

		for (unsigned int i = 0; i < m->points; i++)
		{
			GLfloat *v = &psMesh->textureArray[0][i * 2];

			v[0] = m->texelL[i][0];
			if (invertUV)
			{
				v[1] = 1.0f - m->texelL[i][1];
			}
			else
			{
				v[1] = m->texelL[i][1];
			}
		}

		for (unsigned int i = 0; i < m->faces; ++i)
		{
			Lib3dsFace *face = &m->faceL[i];
			GLuint *v = &psMesh->indexArray[i * 3];

			if (reverseWinding)
			{
				v[0] = face->points[2];
				v[1] = face->points[1];
				v[2] = face->points[0];
			}
			else
			{
				v[0] = face->points[0];
				v[1] = face->points[1];
				v[2] = face->points[2];
			}
		}
	}

	lib3ds_file_free(f);
	return psModel;
}
Example #24
0
void
lib3ds_mesh_read(Lib3dsFile *file, Lib3dsMesh *mesh, Lib3dsIo *io) {
    Lib3dsChunk c;
    uint16_t chunk;

    lib3ds_chunk_read_start(&c, CHK_N_TRI_OBJECT, io);

    while ((chunk = lib3ds_chunk_read_next(&c, io)) != 0) {
        switch (chunk) {
            case CHK_MESH_MATRIX: {
                int i, j;

                lib3ds_matrix_identity(mesh->matrix);
                for (i = 0; i < 4; i++) {
                    for (j = 0; j < 3; j++) {
                        mesh->matrix[i][j] = lib3ds_io_read_float(io);
                    }
                }
                break;
            }

            case CHK_MESH_COLOR: {
                mesh->color = lib3ds_io_read_byte(io);
                break;
            }

            case CHK_POINT_ARRAY: {
                int i;
                uint16_t nvertices = lib3ds_io_read_word(io);
                lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, mesh->vflags != NULL);
                for (i = 0; i < mesh->nvertices; ++i) {
                    lib3ds_io_read_vector(io, mesh->vertices[i]);
                }
                break;
            }

            case CHK_POINT_FLAG_ARRAY: {
                int i;
                uint16_t nflags = lib3ds_io_read_word(io);
                uint16_t nvertices = (mesh->nvertices >= nflags)? mesh->nvertices : nflags;
                lib3ds_mesh_resize_vertices(mesh, nvertices, mesh->texcos != NULL, 1);
                for (i = 0; i < nflags; ++i) {
                    mesh->vflags[i] = lib3ds_io_read_word(io);
                }
                break;
            }

            case CHK_FACE_ARRAY: {
                lib3ds_chunk_read_reset(&c, io);
                face_array_read(file, mesh, io);
                break;
            }

            case CHK_MESH_TEXTURE_INFO: {
                int i, j;

                //FIXME: mesh->map_type = lib3ds_io_read_word(io);

                for (i = 0; i < 2; ++i) {
                    mesh->map_tile[i] = lib3ds_io_read_float(io);
                }
                for (i = 0; i < 3; ++i) {
                    mesh->map_pos[i] = lib3ds_io_read_float(io);
                }
                mesh->map_scale = lib3ds_io_read_float(io);

                lib3ds_matrix_identity(mesh->map_matrix);
                for (i = 0; i < 4; i++) {
                    for (j = 0; j < 3; j++) {
                        mesh->map_matrix[i][j] = lib3ds_io_read_float(io);
                    }
                }
                for (i = 0; i < 2; ++i) {
                    mesh->map_planar_size[i] = lib3ds_io_read_float(io);
                }
                mesh->map_cylinder_height = lib3ds_io_read_float(io);
                break;
            }

            case CHK_TEX_VERTS: {
                int i;
                uint16_t ntexcos = lib3ds_io_read_word(io);
                uint16_t nvertices = (mesh->nvertices >= ntexcos)? mesh->nvertices : ntexcos;;
                if (!mesh->texcos) {
                    lib3ds_mesh_resize_vertices(mesh, nvertices, 1, mesh->vflags != NULL);
                }
                for (i = 0; i < ntexcos; ++i) {
                    mesh->texcos[i][0] = lib3ds_io_read_float(io);
                    mesh->texcos[i][1] = lib3ds_io_read_float(io);
                }
                break;
            }

            default:
                lib3ds_chunk_unknown(chunk, io);
        }
    }

    if (lib3ds_matrix_det(mesh->matrix) < 0.0) {
        /* Flip X coordinate of vertices if mesh matrix
           has negative determinant */
        float inv_matrix[4][4], M[4][4];
        float tmp[3];
        int i;

        lib3ds_matrix_copy(inv_matrix, mesh->matrix);
        lib3ds_matrix_inv(inv_matrix);

        lib3ds_matrix_copy(M, mesh->matrix);
        lib3ds_matrix_scale(M, -1.0f, 1.0f, 1.0f);
        lib3ds_matrix_mult(M, M, inv_matrix);

        for (i = 0; i < mesh->nvertices; ++i) {
            lib3ds_vector_transform(tmp, M, mesh->vertices[i]);
            lib3ds_vector_copy(mesh->vertices[i], tmp);
        }
    }

    lib3ds_chunk_read_end(&c, io);
}
Example #25
0
// TODO: Build own exporter class
void objectExporter::on_buttonBox_accepted()
{
    QString fileName = QFileDialog::getSaveFileName(gloParent, "Save 3ds Object", ".", "3D Object (*.3ds)", 0, 0);

    QList<trackHandler*> trackList = gloParent->getTrackList();
    trackHandler* curTrack = trackList[ui->trackBox->currentIndex()];

    trackMesh* mesh = curTrack->mMesh;

    QVector<float> *vertices = new QVector<float>();
    QVector<unsigned int> *indices = new QVector<unsigned int>();
    QVector<unsigned int> *borders = new QVector<unsigned int>();

    Lib3dsFile *file = lib3ds_file_new();
    file->frames = 360;

    {
        Lib3dsMaterial* mat = lib3ds_material_new("coaster");
        lib3ds_file_insert_material(file, mat, -1);
        mat->diffuse[0] = curTrack->trackColors[0].red()/255.f;
        mat->diffuse[1] = curTrack->trackColors[0].green()/255.f;
        mat->diffuse[2] = curTrack->trackColors[0].blue()/255.f;
    }

    {
        for(int section = 0; section < curTrack->trackData->lSections.size(); ++section) {
            vertices->clear();
            indices->clear();
            borders->clear();
            mesh->build3ds(section, vertices, indices, borders);

            float* fvertices = new float[vertices->size()];
            for(int i = 0; i < vertices->size()/3; ++i) {
                fvertices[3*i+0] = vertices->at(3*i+0);
                fvertices[3*i+1] = -vertices->at(3*i+2);
                fvertices[3*i+2] = vertices->at(3*i+1);

                //exportScreen->doFastExport();
            }
            for(int subIndex = 0; subIndex < borders->size()-2; subIndex+= 2) {
                int fromVIndex = borders->at(subIndex)/3;
                int toVIndex = borders->at(subIndex+2)/3;
                int fromIIndex = borders->at(subIndex+1)/3;
                int toIIndex = borders->at(subIndex+3)/3;

                int i, j;
                QString name = QString::number(section).append(QString("_").append(QString::number(subIndex/2)));
                Lib3dsMesh *mesh = lib3ds_mesh_new(name.toLocal8Bit().data());
                Lib3dsMeshInstanceNode *inst;
                lib3ds_file_insert_mesh(file, mesh, -1);

                lib3ds_mesh_resize_vertices(mesh, toVIndex-fromVIndex, 1, 0);
                for (i = 0; i < toVIndex-fromVIndex; ++i) {
                    lib3ds_vector_copy(mesh->vertices[i], &fvertices[(i+fromVIndex)*3]);
                    mesh->texcos[i][0] = 0.f;
                    mesh->texcos[i][1] = 0.f;
                }

                lib3ds_mesh_resize_faces(mesh, toIIndex-fromIIndex);
                for (i = 0; i < toIIndex-fromIIndex; ++i) {
                    for (j = 0; j < 3; ++j) {
                        mesh->faces[i].index[j] = indices->at(3*(i+fromIIndex)+j)-fromVIndex;
                        mesh->faces[i].material = 0;
                    }
                }
                inst = lib3ds_node_new_mesh_instance(mesh, name.toLocal8Bit().data(), NULL, NULL, NULL);
                lib3ds_file_append_node(file, (Lib3dsNode*)inst, NULL);
            }
            delete[] fvertices;
        }
    }

    {
        Lib3dsCamera *camera;
        Lib3dsCameraNode *n;
        Lib3dsTargetNode *t;
        int i;

        camera = lib3ds_camera_new("camera01");
        lib3ds_file_insert_camera(file, camera, -1);
        lib3ds_vector_make(camera->position, 0.0, -100, 0.0);
        lib3ds_vector_make(camera->target, 0.0, 0.0, 0.0);

        n = lib3ds_node_new_camera(camera);
        t = lib3ds_node_new_camera_target(camera);
        lib3ds_file_append_node(file, (Lib3dsNode*)n, NULL);
        lib3ds_file_append_node(file, (Lib3dsNode*)t, NULL);

        lib3ds_track_resize(&n->pos_track, 37);
        for (i = 0; i <= 36; i++) {
            n->pos_track.keys[i].frame = 10 * i;
            lib3ds_vector_make(n->pos_track.keys[i].value,
                (float)(100.0 * cos(2 * F_PI * i / 36.0)),
                (float)(100.0 * sin(2 * F_PI * i / 36.0)),
                50.0
            );
        }
    }

    if (!lib3ds_file_save(file, fileName.toLocal8Bit().data())) {
         qDebug("ERROR: Saving 3ds file failed!\n");
    }
    lib3ds_file_free(file);

    delete indices;
    delete vertices;
}