예제 #1
0
파일: test_array.c 프로젝트: ASMlover/libc
static void array_object_show(void* A)
{
  fprintf(stdout,
      "  show object of array :\n"
      "\t__array__ -> {\n"
      "\t  object=>0x%p,\n"
      "\t  size=>%d,\n"
      "\t  empty=>'%s',\n"
      "\t  begin=>0x%p,\n"
      "\t  end=>0x%p,\n"
      "\t  front=>0x%p,\n"
      "\t  back=>0x%p,\n"
      "\t}\n", 
      A, array_size(A), (array_empty(A) ? "yes" : "no"), 
      array_begin(A), array_end(A), array_front(A), array_back(A)
      );
}
예제 #2
0
파일: mesh.c 프로젝트: 0ctobyte/ogl
void _mesh_create_material_group(mesh_t *mesh) {
  // Create a new material group
  material_group_t grp;

  // Initialize the index vars
  grp.offset = 0;
  if(array_size(mesh->mtl_grps) > 0) {
    // The offset is the previous groups offset + count
    material_group_t *last_grp = (material_group_t*)array_back(mesh->mtl_grps);
    grp.offset = last_grp->offset+last_grp->count;
  }
  grp.count = 0;

  // Default values for the material in case none exist
  _mesh_init_material(&grp.mtl);

  // Add the material group to the mesh
  array_append(mesh->mtl_grps, &grp);
}
예제 #3
0
파일: mesh.c 프로젝트: 0ctobyte/ogl
bool mesh_load(mesh_t *mesh, const char *objfile) {
  // Initialize the parser struct
  obj_parser_t p;
  if(obj_parser_init(&p, objfile) != 0) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load mesh: %s\n", objfile);
    return false;
  }

  // Initialize the arrays.
  mesh->vattributes = array_create(256, 3*sizeof(GLfloat));
  mesh->indices = array_create(256, sizeof(GLuint));
  mesh->mtl_grps = array_create(2, sizeof(material_group_t));
  
  // Grab the vertex attribute data and place them in separate arrays
  array_t *uv = array_create(256, 3*sizeof(GLfloat));
  array_t *normals = array_create(256, 3*sizeof(GLfloat));
  array_t *mtllib = array_create(16, sizeof(char));

  for(; p.token.type != OBJ_ENDOFFILE; obj_lexer_get_token(&p)) {
    switch(p.token.type) {
    case OBJ_VNTAG:
      // Parse the vertex normals
      obj_parser_vntag(&p, normals);
      break;
    case OBJ_VTTAG:
      // Parse the vertex texture coordinates
      obj_parser_vttag(&p, uv);
      break;
    case OBJ_VTAG:
      // Parse the vertex position coordinates
      obj_parser_vtag(&p, mesh->vattributes);

      // Now append zero vectors for the normal and texture coordinate attributes
      // The z value is initially set to -10.0f to indicate that the attribute is currently empty
      GLfloat u[3] = {0.0f, 0.0f, -10.0f};
      array_append(mesh->vattributes, &u);
      array_append(mesh->vattributes, &u);
      break;
    case OBJ_MTLLIBTAG:
      // Parse the name of the mtllib file
      obj_parser_mtllibtag(&p, mtllib);

      // Get the mtllib filename
      array_prepend_str(mtllib, "resources/");
      break;
    default:
      break;
    }
  }

  // If a mtllib file was specified, parse it
  array_t *mtl_list = array_create(2, sizeof(material_def_t));
  if(array_size(mtllib) > 0) _mesh_load_material(mesh, array_data(mtllib), mtl_list);

  array_t *i_positions = array_create(4, sizeof(GLuint));
  array_t *i_texcoords = array_create(4, sizeof(GLuint));
  array_t *i_normals = array_create(4, sizeof(GLuint));

  // Parse the indices as they are read in and place the vertex attributes in the correct index in the vertex attribute array
  for(p.c_index = 0, p.token.type = OBJ_UNKNOWN; p.token.type != OBJ_ENDOFFILE; obj_lexer_get_token(&p)) {
    switch(p.token.type) {
    case OBJ_FTAG:
      {
        // Parse the face indices
        array_clear(i_positions);
        array_clear(i_texcoords);
        array_clear(i_normals);
        obj_parser_ftag(&p, i_positions, i_texcoords, i_normals);

        mesh->num_faces++;
     
        // Create a material group if none exist
        // We might have obj files with only one group of faces and no materials 
        if(array_size(mesh->mtl_grps) == 0) _mesh_create_material_group(mesh);

        // Add the indices to the last material group in the list
        material_group_t *grp = (material_group_t*)array_back(mesh->mtl_grps);

        // For each vertex attribute specified, add them to the material group's indices list duplicating the attribute if necessary
        for(uint64_t i = 0; i < 3; ++i) {
          
          // Indices start from 1 in the Wavefront OBJ format
          // Get all the indices for the each vertex attributes
          GLuint index = *((GLuint*)array_at(i_positions, i))-1;
          GLuint v_index = (array_size(i_texcoords) > 0) ? *((GLuint*)array_at(i_texcoords, i)) : 0;
          GLuint n_index = (array_size(i_normals) > 0) ? *((GLuint*)array_at(i_normals, i)) : 0;
         
          GLfloat v[3] = {0.0f, 0.0f, 0.0f};
          GLfloat n[3] = {0.0f, 0.0f, 0.0f};
          bool duplicate = false;

          // Make sure the texture coordinate was specified
          if(v_index != 0) {
            v_index--;
            memcpy(v, array_at(uv, v_index), 3*sizeof(GLfloat));

            // Check if the vertex needs to be duplicated, if the texture coordinates are different for the same vertex
            GLfloat *u = array_at(mesh->vattributes, index*3+1);

            if((u[2] != -10.0f)&& (u[0] != v[0] || u[1] != v[1])) duplicate = true;
          } 

          // Make sure a normal was specified
          if(n_index != 0) {
            n_index--;
            memcpy(n, array_at(normals, n_index), 3*sizeof(GLfloat));

            // Check if the vertex needs to be duplicated, if the normals are different for the same vertex
            GLfloat *u = array_at(mesh->vattributes, index*3+2);

            if((u[2] != -10.0f) && (u[0] != n[0] || u[1] != n[1] || u[2] != n[2])) duplicate = true;
          }

          // Duplicate the vertex attribute if needed
          if(duplicate) {
            GLfloat l[3] = {0.0f, 0.0f, 0.0f};
            memcpy(l, array_at(mesh->vattributes, index*3), 3*sizeof(GLfloat));
            array_append(mesh->vattributes, l);
            index = ((GLuint)array_size(mesh->vattributes)-1)/3;
            array_append(mesh->vattributes, v);
            array_append(mesh->vattributes, n);
          } else {
            // Set the texture coordinate and normal in the vertex attribute array 
            array_set(mesh->vattributes, index*3+1, v);
            array_set(mesh->vattributes, index*3+2, n);
          }

          // Append the index into the index array
          array_append(mesh->indices, &index);
        }
        
        // Increment the count of indices for the material group
        grp->count += 3;

        break;
      }
    case OBJ_USEMTLTAG:
      {
        array_t *mtl_name = array_create(8, sizeof(char));
        obj_parser_usemtltag(&p, mtl_name);

        // Start a new material group using this material
        _mesh_create_material_group(mesh);
        
        // Load the material data for the material group
        // Have to find the material with the specified material name in the material definition list
        bool found_mtl = false;
        for(uint64_t i = 0; i < array_size(mtl_list); i++) {
          material_def_t *mtl_def = array_at(mtl_list, i);
          if(strcmp((char*)array_data(mtl_def->mtl_name), (char*)array_data(mtl_name)) == 0) {
            material_group_t *grp = (material_group_t*)array_back(mesh->mtl_grps);

            // Copy the material data
            memcpy(&grp->mtl, &mtl_def->mtl, sizeof(material_t));
            found_mtl = true;
            break;
          }
        }

        if(!found_mtl) {
          SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not find material: \'%s\'\n", (char*)array_data(mtl_name));
        }

        array_delete(mtl_name);
        break;
      }
    default:
      break;
    }
  }

  // Cleanup temp arrays
  array_delete(uv);
  array_delete(normals);
  array_delete(mtllib);
  array_delete(i_positions);
  array_delete(i_texcoords);
  array_delete(i_normals);

  // Cleanup up the material definition list
  for(uint64_t i = 0; i < array_size(mtl_list); i++) {
    material_def_t *mtl_def = (material_def_t*)array_at(mtl_list, i);
    array_delete(mtl_def->mtl_name);
  }
  array_delete(mtl_list);
  
  // Delete the parser struct
  obj_parser_free(&p);

  // Generate and fill the OpenGL buffers
  _mesh_gen_buffers(mesh);

  // Print some stats
  SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Mesh loaded with %lu vertex attributes and %lu faces\n", array_size(mesh->vattributes)/3, mesh->num_faces);

  return true;
}
예제 #4
0
파일: mesh.c 프로젝트: 0ctobyte/ogl
bool _mesh_load_material(mesh_t *mesh, const char *mtl_filename, array_t *mtl_list) {
  // Initialize the parser struct
  mtl_parser_t p;
  if(mtl_parser_init(&p, mtl_filename) != 0) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load mtllib: %s\n", mtl_filename);
    return false;
  }

  for(; p.token.type != MTL_ENDOFFILE; mtl_lexer_get_token(&p)) {
    // Get the latest material definition
    material_def_t *mtl_def = (array_size(mtl_list) > 0) ? (material_def_t*)array_back(mtl_list): NULL;
    
    switch(p.token.type) {
    case MTL_NEWMTLTAG:
      {
        // Append a new material definition to the list
        mtl_parser_expect(&p, MTL_IDENTIFIER);
        
        material_def_t newmtl;
        newmtl.mtl_name = array_create(array_size(p.token.lexeme), sizeof(char));
        
        array_copy(newmtl.mtl_name, p.token.lexeme);
        _mesh_init_material(&newmtl.mtl);
        
        array_append(mtl_list, &newmtl);
        break;
      }
    case MTL_NSTAG:
      {
        // Parse the shininess exponent
        if(mtl_parser_found(&p, MTL_FLOAT) || mtl_parser_found(&p, MTL_UINT)) {
          mtl_def->mtl.shininess = strtof(array_data(p.token.lexeme), NULL);
        }
        break;
      }
    case MTL_KATAG:
      {
        // Parse the ambient reflectivity
        for(uint64_t i = 0; i < 3; i++) {
          mtl_parser_expect(&p, MTL_FLOAT);
          mtl_def->mtl.ambient[i] = strtof(array_data(p.token.lexeme), NULL);
        }
        break;
      }
    case MTL_KDTAG:
      {
        // Parse the diffuse reflectivity
        for(uint64_t i = 0; i < 3; i++) {
          mtl_parser_expect(&p, MTL_FLOAT);
          mtl_def->mtl.diffuse[i] = strtof(array_data(p.token.lexeme), NULL);
        }
        break;
      }
    case MTL_KSTAG:
      {
        // Parse the specular reflectivity
        for(uint64_t i = 0; i < 3; i++) {
          mtl_parser_expect(&p, MTL_FLOAT);
          mtl_def->mtl.specular[i] = strtof(array_data(p.token.lexeme), NULL);
        }
        break;
      }
    case MTL_DTAG:
      {
        // Parse the dissolve/transparency value
        if(mtl_parser_found(&p, MTL_FLOAT) || mtl_parser_found(&p, MTL_UINT)) {
          mtl_def->mtl.transparency = strtof(array_data(p.token.lexeme), NULL);
        }
        break;
      }
    case MTL_MAPKDTAG:
      {
        // Parse the diffuse texture map
        mtl_parser_expect(&p, MTL_IDENTIFIER);
        
        array_t *texname = array_create(array_size(p.token.lexeme), sizeof(char));
        array_copy(texname, p.token.lexeme);
        array_prepend_str(texname, "resources/");
        
        // Load the texture from the file
        _mesh_load_texture(mesh, &mtl_def->mtl, array_data(texname));
        array_delete(texname);
        break;
      }
    default:
      break;
    }
  }

  // Delete the parser struct
  mtl_parser_free(&p);

  return true;
}