コード例 #1
0
ファイル: obj.c プロジェクト: 0ctobyte/ogl
void obj_parser_vntag(obj_parser_t *p, array_t *a) {
  // vn = "vn", whitespace, float, whitespace, float, whitespace, float
  float v[3];

  for(uint64_t i = 0; i < 3; ++i) {
    obj_parser_expect(p, OBJ_FLOAT);
    v[i] = strtof(array_data(p->token.lexeme), NULL);
  }

  array_append(a, &v);
}
コード例 #2
0
ファイル: obj.c プロジェクト: 0ctobyte/ogl
void obj_parser_vttag(obj_parser_t *p, array_t *a) {
  // vt = "vt", whitespace, float, whitespace, float, [whitespace, float]
  float v[3];

  for(uint64_t i = 0; i < 2; ++i) {
    obj_parser_expect(p, OBJ_FLOAT);
    v[i] = strtof(array_data(p->token.lexeme), NULL);
  }

  if(obj_parser_found(p, OBJ_FLOAT)) {
    // In case we get a 3d texture coordinate
    v[2] = strtof(array_data(p->token.lexeme), NULL);
  } else {
    v[2] = 0.0f;
  }

  // Blender's UV coordinate system is vertically flipped compared to OpenGL's
  v[1] = 1 - v[1];
  array_append(a, &v);
}
コード例 #3
0
ファイル: obj.c プロジェクト: 0ctobyte/ogl
void obj_parser_vtag(obj_parser_t *p, array_t *a) {
  // v = 'v', whitespace, float, whitespace, float, whitespace, float
  // A vtag is followed by 3 floats
  float v[3];

  for(uint64_t i = 0; i < 3; ++i) {
    obj_parser_expect(p, OBJ_FLOAT);
    v[i] = strtof(array_data(p->token.lexeme), NULL);
  }

  array_append(a, &v);
}
コード例 #4
0
ファイル: obj.c プロジェクト: 0ctobyte/ogl
void obj_parser_ftag(obj_parser_t *p, array_t *i_positions, array_t *i_texcoords, array_t *i_normals) {
  // f = 'f', whitespace, ((uint, whitespace, uint, whitespace, uint
  // | uint, separator, uint, whitespace, uint, separator, uint, whitespace, uint, separator, uint
  // | uint, separator, uint, separator, uint, whitespace, uint, separator, uint, separator, uint, whitespace, uint, separator, uint, separator, uint
  // | uint, separator, separator, uint, whitespace, uint, separator, separator, uint, whitespace, uint, separator, separator, uint)
  
  // 3 sets of indices for each vertex
  for(uint64_t i = 0; i < 3; ++i) {
    obj_parser_expect(p, OBJ_UINT);
    uint32_t index = (uint32_t)strtoul(array_data(p->token.lexeme), NULL, 10);
    array_append(i_positions, &index);

    if(obj_parser_found(p, OBJ_SEPARATOR)) {
      // Double separator means only normal index specified
      if(obj_parser_found(p, OBJ_SEPARATOR)) {
        obj_parser_expect(p, OBJ_UINT);

        index = (uint32_t)strtoul(array_data(p->token.lexeme), NULL, 10);
        array_append(i_normals, &index);
      } else {
        // One separator indicates a texcoord 
        obj_parser_expect(p, OBJ_UINT);

        index = (uint32_t)strtoul(array_data(p->token.lexeme), NULL, 10);
        array_append(i_texcoords, &index);

        // If another separator is found then a normal is also specified
        if(obj_parser_found(p, OBJ_SEPARATOR)) {
          obj_parser_expect(p, OBJ_UINT);

          index = (uint32_t)strtoul(array_data(p->token.lexeme), NULL, 10);
          array_append(i_normals, &index);
        }
      }
    }
  }
}
コード例 #5
0
ファイル: obj.c プロジェクト: 0ctobyte/ogl
uint64_t obj_lexer_get_token(obj_parser_t *p) {
  obj_token_type_t prev_type = p->token.type;
  p->token.type = OBJ_UNKNOWN;

  // Skip comment lines
  while(p->fstring[p->c_index] == '#') {
    p->c_index += strcspn(&p->fstring[p->c_index], "\n");
    while(isspace(p->fstring[p->c_index])) p->c_index++;
  }

  // Skip all the white spaces and newlines
  while(isspace(p->fstring[p->c_index])) p->c_index++;

  // Check if end of file has been reached
  if(p->c_index >= p->fsize) {
    p->token.type = OBJ_ENDOFFILE;
    return 1;
  }

  array_clear(p->token.lexeme);

  // Read characters until the next whitespace or separator 
  while(!isspace(p->fstring[p->c_index]) && p->fstring[p->c_index] != '/') {
    char c = p->fstring[p->c_index++];
    array_append(p->token.lexeme, &c);
  }
  size_t tok_len = array_size(p->token.lexeme);

  // If token length is zero, it must be the separator...right?
  if(tok_len == 0) {
    array_append(p->token.lexeme, &p->fstring[p->c_index++]);
    tok_len++;
  }

  char c = 0;
  array_append(p->token.lexeme, &c);

  // Get the actual data from the array
  char *lexeme = (char*)array_data(p->token.lexeme);

  // Check if it is a separator
  if(lexeme[0] == '/') {
    p->token.type = OBJ_ERROR;

    if(tok_len != 1) return 1;

    p->token.type = OBJ_SEPARATOR;
    return 0;
  }

  // Check if this token is an identifier depending on the previous type
  if(prev_type == OBJ_MTLLIBTAG || prev_type == OBJ_USEMTLTAG) {
    p->token.type = OBJ_IDENTIFIER;
    return 0;
  }

  // Check if the token is a tag: r'vn|vt|v|f'
  if(isalpha(lexeme[0])) {
    // Which kind of tag?
    if(strcmp(lexeme, "vn") == 0) p->token.type = OBJ_VNTAG;
    else if(strcmp(lexeme, "vt") == 0) p->token.type = OBJ_VTTAG;
    else if(strcmp(lexeme, "v") == 0) p->token.type = OBJ_VTAG;
    else if(strcmp(lexeme, "f") == 0) p->token.type = OBJ_FTAG;
    else if(strcmp(lexeme, "mtllib") == 0) p->token.type = OBJ_MTLLIBTAG;
    else if(strcmp(lexeme, "usemtl") == 0) p->token.type = OBJ_USEMTLTAG;
    else p->token.type = OBJ_ERROR;

    return (p->token.type == OBJ_ERROR) ? 1 : 0;
  }

  // Check if it is a floating point number: -?[0-9]+\.[0-9]+
  if(strchr(lexeme, '.') != NULL && (lexeme[0] == '-' || isdigit(lexeme[0]))) {
    p->token.type = OBJ_ERROR;

    // Confirm that this is a correctly formatted float
    size_t index = 0;
    if(lexeme[index] == '-') index++;
    while(isdigit(lexeme[index++]));

    // Must be a period
    if(lexeme[(index-1)] != '.') return 1;

    // Continue confirming digits in the decimal portion
    while(isdigit(lexeme[index++]));

    // If index is the number as tok_len then we have successfully confirmed a floating point number
    if(--index != tok_len) return 1;

    p->token.type = OBJ_FLOAT;
    return 0;
  }

  // Check if it is a uint: [0-9]+
  if(isdigit(lexeme[0])) {
    p->token.type = OBJ_ERROR;

    // Confirm that this is a correctly formatted uint
    size_t index = 0;
    while(isdigit(lexeme[index++]));

    // If index is the same number as tok_len then we have successfully confirmed a uint
    if(--index != tok_len) return 1;

    p->token.type = OBJ_UINT;
    return 0;
  }

  return 0;
}
コード例 #6
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;
}
コード例 #7
0
ファイル: text_renderer.c プロジェクト: arkanis/hdswitch
static text_renderer_cell_p find_free_cell_or_revoke_unused_cell(text_renderer_p renderer, text_renderer_font_p font, uint32_t glyph_width, uint32_t glyph_height, uint32_t texture_width, uint32_t texture_height, size_t* line_idx, size_t* cell_idx) {
	// Padding between the glyphs
	const uint32_t padding = 1;
	// Keep track of the texture coordinates so we know where our cell is on the texture
	uint32_t x = 0, y = 0;
	
	// First search for a line with the matching height
	for(size_t i = 0; i < renderer->lines->length; i++) {
		text_renderer_line_p line = &array_data(renderer->lines, text_renderer_line_t)[i];
		
		if (line->height == glyph_height) {
			// We found a line with matching height, now look if we can get our cell in there
			x = 0;
			for(size_t j = 0; j < line->cells->length; j++) {
				text_renderer_cell_p current_cell = array_elem_ptr(line->cells, j);
				x += current_cell->width + padding;
			}
			
			if (x + glyph_width <= texture_width) {
				// There is space left at the end of this line, add our cell here
				text_renderer_cell_p cell = array_append_ptr(line->cells);
				memset(cell, 0, sizeof(text_renderer_cell_t));
				
				cell->x = x;
				cell->y = y;
				cell->width = glyph_width;
				
				*line_idx = i;
				*cell_idx = line->cells->length - 1;
				return cell;
			}
			
			// No space at end of line, search next line
		}
		
		y += line->height + padding;
	}
	
	// We haven't found a matching line or every matching line was full. Anyway add a new line
	// if there is space left at the bottom of the texture and put the cell in there.
	if (y + glyph_height + padding <= texture_height) {
		text_renderer_line_p line = array_append_ptr(renderer->lines);
		line->height = glyph_height;
		line->cells = array_of(text_renderer_cell_t);
		
		text_renderer_cell_p cell = array_append_ptr(line->cells);
		memset(cell, 0, sizeof(text_renderer_cell_t));
		
		cell->x = x;
		cell->y = y;
		cell->width = glyph_width;
		
		*line_idx = renderer->lines->length - 1;
		*cell_idx = 0;
		return cell;
	}
	
	// We would like to add a new line but there is not enough free space at the bottom
	// to the texture. For now just give up.
	*line_idx = (size_t)-1;
	*cell_idx = (size_t)-1;
	return NULL;
}
コード例 #8
0
ファイル: mesh.c プロジェクト: 0ctobyte/ogl
void _mesh_gen_buffers(mesh_t *mesh) {
  // Generate the name for the vertex array object (VAO)
  glGenVertexArrays(1, &mesh->vao);
  glBindVertexArray(mesh->vao);

  // Create names for the vertex buffer object (VBO) and the index buffer object
  glGenBuffers(1, &mesh->vbo);
  glGenBuffers(1, &mesh->ibo);

  // Copy the index data into the index buffer
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(array_size(mesh->indices)*sizeof(GLuint)), array_data(mesh->indices), GL_STATIC_DRAW);

  // Copy the vertex data into the vertex buffer
  glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
  glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)(array_size(mesh->vattributes)*3*sizeof(GLfloat)), array_data(mesh->vattributes), GL_STATIC_DRAW);

  // Set and enable the vertex attributes. 0 = vertex position, 1 = vertex texture coordinates, 2 = vertex normals
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*)0);

  glEnableVertexAttribArray(1);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));

  glEnableVertexAttribArray(2);
  glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat)));

  // Unbind VAO
  glBindVertexArray(0);
}
コード例 #9
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;
}
コード例 #10
0
ファイル: check-axis.c プロジェクト: LouisStrous/LUX
END_TEST

START_TEST(axis_201_eachrow)
{
  int dims[] = { 3, 4, 2 };
  int32_t iq = array_scratch(LUX_INT32, 3, dims);
  iq = lux_indgen(1, &iq);
  ck_assert_msg(iq > 0, "Cannot create array");
  int three =  3;
  int32_t axes = array_scratch(LUX_INT32, 1, &three);
  pointer axesp;
  axesp.v = array_data(axes);
  axesp.l[0] = 2;
  axesp.l[1] = 0;
  axesp.l[2] = 1;
  loopInfo srci;
  pointer srcp;
  ck_assert_int_eq(standardLoop(iq, axes, SL_EACHROW, LUX_INT32, &srci, &srcp, NULL, NULL, NULL), LUX_OK);
  ck_assert_int_eq(srci.ndim, sizeof(dims)/sizeof(*dims));
  ck_assert_int_eq(srci.nelem, dims[0]*dims[1]*dims[2]);
  int i;
  for (i = 0; i < srci.ndim; i++)
    ck_assert_int_eq(srci.coords[i],    0);
  /* specified dimensions */
  ck_assert_int_eq(srci.dims[0],        dims[0]);
  ck_assert_int_eq(srci.dims[1],        dims[1]);
  ck_assert_int_eq(srci.dims[2],        dims[2]);
  ck_assert_int_eq(srci.singlestep[0],  1); /* one step along dimension 0 */
  ck_assert_int_eq(srci.singlestep[1],  dims[0]); /* along dimension 1 */
  ck_assert_int_eq(srci.singlestep[2],  dims[0]*dims[1]); /* along dim 2 */
  /* specified axes */
  ck_assert_int_eq(srci.naxes,          3);
  ck_assert_int_eq(srci.axes[0],        2);
  ck_assert_int_eq(srci.axes[1],        0);
  ck_assert_int_eq(srci.axes[2],        1);
  /* compressed/rearranged dimensions; we loop along dimension 2
     first, and then along dimensions 0 and 1. */
  ck_assert_int_eq(srci.rndim,          3);
  ck_assert_int_eq(srci.rdims[0],       dims[2]); /* 2 */
  ck_assert_int_eq(srci.rdims[1],       dims[0]); /* 3 */
  ck_assert_int_eq(srci.rdims[2],       dims[1]); /* 4 */
  ck_assert_int_eq(srci.rsinglestep[0], dims[0]*dims[1]); /* 12 */
  ck_assert_int_eq(srci.rsinglestep[1], 1);
  ck_assert_int_eq(srci.rsinglestep[2], dims[0]); /* 3 */
  /* how many elements to advance the pointer to go to the next item
     in the desired order? */
  ck_assert_int_eq(srci.step[0],        srci.rsinglestep[0]); /* 12 */
  /* how many elements to advance the pointer additionally to go to
     the next item in the desired order when reaching the end of the
     first selected axis?  Then we've advanced step[0] elements
     rdims[0] = dims[1] times, but want to end up having advanced
     rsinglestep[1] = 1 element. */
  ck_assert_int_eq(srci.step[1],        srci.rsinglestep[1] - srci.rdims[0]*srci.step[0]); /* 1 - 2*12 = -23 */
  /* how many elements to advance the pointer additionally to go to
     the next item in the desired order when reaching the end of the
     second selected axis?  Then we've advanced step[0] elements
     rdims[0]*rdims[1] times, and step[1] elements rdims[1] times, but
     want to end up having advanced rsinglestep[2] elements. */
  ck_assert_int_eq(srci.step[2],        srci.rsinglestep[2] - srci.step[0]*srci.rdims[0]*srci.rdims[1] - srci.step[1]*srci.rdims[1]);

  ck_assert_int_eq(srci.raxes[0],       2);
  ck_assert_int_eq(srci.raxes[1],       0);
  ck_assert_int_eq(srci.raxes[2],       1);

  ck_assert_int_eq(srci.iraxes[0],      1);
  ck_assert_int_eq(srci.iraxes[1],      2);
  ck_assert_int_eq(srci.iraxes[2],      0);

  ck_assert_int_eq(srci.axisindex,      0);
  ck_assert_int_eq(srci.advanceaxis,    1);
  int count = 0;
  /* advanceLoop returns 0 while inside the first specified axis,
     1 when at the end of the first specified axis,
     2 when at the end of the second specified axis,
     3 when at the end of the third specified axis. */
  /* axes 2,0,1 → dimension sizes 2,3,4 */
  int expect_a[] = {1,1,2,1,1,2,1,1,2,1, 1, 3};
  int expect_i[] = {0,1,2,3,4,5,6,7,8,9,10,11};
  int ok;
  int size = dims[0]*dims[1];
  do {
    fail_unless(count < size, "Out of bounds"); /* stay within bounds */
    fail_unless(*srcp.l == expect_i[count],
                "Element bad; expect %d, got %d, count = %d",
                expect_i[count], *srcp.l, count);
    int c0 = 0;                 /* always 0 because of SL_EACHROW */
    int c1 = count % srci.rdims[1];
    int c2 = count/srci.rdims[1];
    fail_unless(srci.coords[0] == c0,
                "Coordinate 0 bad; expect %d, got %d, count = %d",
                c0, srci.coords[0], count);
    fail_unless(srci.coords[1] == c1,
                "Coordinate 1 bad; expect %d, got %d, count = %d",
                c1, srci.coords[1], count);
    fail_unless(srci.coords[2] == c2,
                "Coordinate 2 bad; expect %d, got %d, count = %d",
                c2, srci.coords[2], count);
    /* we have to take care of advancing along the first axis
       ourselves, because of SL_EACHROW */
    srcp.l += srci.rsinglestep[0]*srci.rdims[0];
    ok = advanceLoop(&srci, &srcp);
    fail_unless(ok == expect_a[count],
                "advanceLoop return bad; expect %d, got %d, count = %d",
                expect_a[count], ok, count);
    ++count;
  } while (ok < srci.rndim);
  ck_assert_int_eq(count, size);
}
コード例 #11
0
ファイル: check-axis.c プロジェクト: LouisStrous/LUX
END_TEST

START_TEST(axis_102)
{
  int dims[] = { 3, 4, 2 };
  int32_t iq = array_scratch(LUX_INT32, 3, dims);
  iq = lux_indgen(1, &iq);
  ck_assert_msg(iq > 0, "Cannot create array");
  int one =  1;
  int32_t axes = array_scratch(LUX_INT32, 1, &one); /* axis index 1 */
  pointer axesp;
  axesp.v = array_data(axes);
  *axesp.l = 1;
  loopInfo srci;
  pointer srcp;
  ck_assert_int_eq(standardLoop(iq, axes, 0, LUX_INT32, &srci, &srcp, NULL, NULL, NULL), LUX_OK);
  ck_assert_int_eq(srci.ndim, sizeof(dims)/sizeof(*dims));
  ck_assert_int_eq(srci.nelem, dims[0]*dims[1]*dims[2]);
  int i;
  for (i = 0; i < srci.ndim; i++)
    ck_assert_int_eq(srci.coords[i],    0);
  /* specified dimensions */
  ck_assert_int_eq(srci.dims[0],        dims[0]);
  ck_assert_int_eq(srci.dims[1],        dims[1]);
  ck_assert_int_eq(srci.dims[2],        dims[2]);
  ck_assert_int_eq(srci.singlestep[0],  1); /* one step along dimension 0 */
  ck_assert_int_eq(srci.singlestep[1],  dims[0]); /* along dimension 1 */
  ck_assert_int_eq(srci.singlestep[2],  dims[0]*dims[1]); /* along dim 2 */
  /* specified axes */
  ck_assert_int_eq(srci.naxes,          1);
  ck_assert_int_eq(srci.axes[0],        1); /* loop along axis 1 */
  /* compressed/rearranged dimensions; we loop along dimension 1
     first, and then along dimensions 0 and 2. */
  ck_assert_int_eq(srci.rndim,          3);
  ck_assert_int_eq(srci.rdims[0],       dims[1]); /* 4 */
  ck_assert_int_eq(srci.rdims[1],       dims[0]); /* 3 */
  ck_assert_int_eq(srci.rdims[2],       dims[2]); /* 2 */
  ck_assert_int_eq(srci.rsinglestep[0], dims[0]); /* 3 */
  ck_assert_int_eq(srci.rsinglestep[1], 1);
  ck_assert_int_eq(srci.rsinglestep[2], dims[0]*dims[1]); /* 12 */
  /* how many elements to advance the pointer to go to the next item
     in the desired order? */
  ck_assert_int_eq(srci.step[0],        srci.rsinglestep[0]); /* 3 */
  /* how many elements to advance the pointer additionally to go to
     the next item in the desired order when reaching the end of the
     first selected axis?  Then we've advanced step[0] elements
     rdims[0] = dims[1] times, but want to end up having advanced
     rsinglestep[1] = 1 element. */
  ck_assert_int_eq(srci.step[1],        srci.rsinglestep[1] - srci.rdims[0]*srci.step[0]); /* 1 - 4*3 = -11 */
  /* how many elements to advance the pointer additionally to go to
     the next item in the desired order when reaching the end of the
     second selected axis?  Then we've advanced step[0] elements
     rdims[0]*rdims[1] times, and step[1] elements rdims[1] times, but
     want to end up having advanced rsinglestep[2] elements. */
  ck_assert_int_eq(srci.step[2],        srci.rsinglestep[2] - srci.step[0]*srci.rdims[0]*srci.rdims[1] - srci.step[1]*srci.rdims[1]);

  ck_assert_int_eq(srci.raxes[0],       1);
  ck_assert_int_eq(srci.raxes[1],       0);
  ck_assert_int_eq(srci.raxes[2],       2);

  ck_assert_int_eq(srci.iraxes[0],      1);
  ck_assert_int_eq(srci.iraxes[1],      0);
  ck_assert_int_eq(srci.iraxes[2],      2);

  ck_assert_int_eq(srci.axisindex,      0);
  ck_assert_int_eq(srci.advanceaxis,    0);
  int count = 0;
  /* advanceLoop returns 0 while inside the first specified axis,
     1 when at the end of the first specified axis,
     2 when at the end of the second specified axis,
     3 when at the end of the third specified axis. */
  /* axes 1,0,2 → dimension sizes 4,3,2 */
  int expect_a[] = {0,0,0,1,0,0,0,1,0,0,0,2,
                    0,0,0,1,0,0,0,1,0,0,0,3};
  int expect_i[] = { 0, 3, 6, 9, 1, 4, 7,10, 2, 5, 8,11, 
                    12,15,18,21,13,16,19,22,14,17,20,23};
  int ok;
  int size = array_size(iq);
  do {
    fail_unless(count < size, "Out of bounds"); /* stay within bounds */
    fail_unless(*srcp.l == expect_i[count],
                "Element bad; expect %d, got %d, count = %d",
                expect_i[count], *srcp.l, count);
    int c0 = count % srci.rdims[0];
    int c1 = (count/srci.rdims[0]) % srci.rdims[1];
    int c2 = count/(srci.rdims[0]*srci.rdims[1]);
    fail_unless(srci.coords[0] == c0,
                "Coordinate 0 bad; expect %d, got %d, count = %d",
                c0, srci.coords[0], count);
    fail_unless(srci.coords[1] == c1,
                "Coordinate 1 bad; expect %d, got %d, count = %d",
                c1, srci.coords[1], count);
    fail_unless(srci.coords[2] == c2,
                "Coordinate 2 bad; expect %d, got %d, count = %d",
                c2, srci.coords[2], count);
    ok = advanceLoop(&srci, &srcp);
    fail_unless(ok == expect_a[count],
                "advanceLoop return bad; expect %d, got %d, count = %d",
                expect_a[count], ok, count);
    ++count;
  } while (ok < srci.rndim);
  ck_assert_int_eq(count, size); /* we did all elements */
}
コード例 #12
0
ファイル: mtl.c プロジェクト: 0ctobyte/ogl
uint64_t mtl_lexer_get_token(mtl_parser_t *p) {
  mtl_token_type_t prev_type = p->token.type;
  p->token.type = MTL_UNKNOWN;

  // Skip comment lines
  while(p->fstring[p->c_index] == '#') {
    p->c_index += strcspn(&p->fstring[p->c_index], "\n");
    while(isspace(p->fstring[p->c_index])) p->c_index++;
  }

  // Skip all white spaces
  while(isspace(p->fstring[p->c_index])) p->c_index++;

  // Check if end of file has been reached
  if(p->c_index >= p->fsize) {
    p->token.type = MTL_ENDOFFILE;
    return 1;
  }

  array_clear(p->token.lexeme);

  // Read characters until the next whitespace or separator 
  while(!isspace(p->fstring[p->c_index])) {
    char c = p->fstring[p->c_index++];
    array_append(p->token.lexeme, &c);
  }

  size_t tok_len = array_size(p->token.lexeme);

  char c = 0;
  array_append(p->token.lexeme, &c);

  // Get the actual data from the array
  char *lexeme = (char*)array_data(p->token.lexeme);

  // Check if this token is an identifier depending on the the previous token type
  if(prev_type >= MTL_MAPKATAG && prev_type <= MTL_NEWMTLTAG) {
    p->token.type = MTL_IDENTIFIER;
    return 0;
  }

  // Check if the token is a tag
  if(isalpha(lexeme[0])) {
    // Which kind of tag
    if(strcmp(lexeme, "Ns") == 0) p->token.type = MTL_NSTAG;
    else if(strcmp(lexeme, "Ka") == 0) p->token.type = MTL_KATAG;
    else if(strcmp(lexeme, "Kd") == 0) p->token.type = MTL_KDTAG;
    else if(strcmp(lexeme, "Ks") == 0) p->token.type = MTL_KSTAG;
    else if(strcmp(lexeme, "d") == 0) p->token.type = MTL_DTAG;
    else if(strcmp(lexeme, "map_Ka") == 0) p->token.type = MTL_MAPKATAG;
    else if(strcmp(lexeme, "map_Kd") == 0) p->token.type = MTL_MAPKDTAG;
    else if(strcmp(lexeme, "map_Ks") == 0) p->token.type = MTL_MAPKSTAG;
    else if(strcmp(lexeme, "map_Bump") == 0) p->token.type = MTL_MAPBUMPTAG;
    else if(strcmp(lexeme, "map_d") == 0) p->token.type = MTL_MAPDTAG;
    else if(strcmp(lexeme, "newmtl") == 0) p->token.type = MTL_NEWMTLTAG;
    else p->token.type = MTL_ERROR;

    return (p->token.type == MTL_ERROR) ? 1 : 0;
  }

  // Check if it is a floating point number: -?[0-9]+\.[0-9]+
  if(strchr(lexeme, '.') != NULL && (lexeme[0] == '-' || isdigit(lexeme[0]))) {
    p->token.type = MTL_ERROR;

    // Confirm that this is a correctly formatted float
    size_t index = 0;
    if(lexeme[index] == '-') index++;
    while(isdigit(lexeme[index++]));

    // Must be a period
    if(lexeme[(index-1)] != '.') return 1;

    // Continue confirming digits in the decimal portion
    while(isdigit(lexeme[index++]));

    // If index is the number as tok_len then we have successfully confirmed a floating point number
    if(--index != tok_len) return 1;

    p->token.type = MTL_FLOAT;
    return 0;
  }

  // Check if it is a uint: [0-9]+
  if(isdigit(lexeme[0])) {
    p->token.type = MTL_ERROR;

    // Confirm that this is a correctly formatted uint
    size_t index = 0;
    while(isdigit(lexeme[index++]));

    // If index is the same number as tok_len then we have successfully confirmed a uint
    if(--index != tok_len) return 1;

    p->token.type = MTL_UINT;
    return 0;
  }

  return 0;
}