md2 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/.document +5 -0
  2. data/.gitignore +26 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +174 -0
  5. data/Rakefile +51 -0
  6. data/VERSION +1 -0
  7. data/bin/md2_to_json +33 -0
  8. data/ext/md2/extconf.rb +3 -0
  9. data/ext/md2/md2.c +95 -0
  10. data/lib/md2.rb +97 -0
  11. data/lib/md2/command.rb +63 -0
  12. data/lib/md2/errors.rb +13 -0
  13. data/lib/md2/frame.rb +61 -0
  14. data/lib/md2/header.rb +37 -0
  15. data/lib/md2/normals.rb +81 -0
  16. data/lib/md2/triangle.rb +9 -0
  17. data/lib/md2/vertex.rb +33 -0
  18. data/md2.gemspec +117 -0
  19. data/spec/lib/md2/frame_spec.rb +13 -0
  20. data/spec/lib/md2/header_spec.rb +21 -0
  21. data/spec/lib/md2_spec.rb +66 -0
  22. data/spec/spec_helper.rb +40 -0
  23. data/spec/support/crafty/Crafty.BMP +0 -0
  24. data/spec/support/crafty/Crafty.pcx +0 -0
  25. data/spec/support/crafty/Crafty.txt +113 -0
  26. data/spec/support/crafty/Weapon.md2 +0 -0
  27. data/spec/support/crafty/Weapon.pcx +0 -0
  28. data/spec/support/crafty/crafty.md2 +0 -0
  29. data/spec/support/laalaa/laalaa.md2 +0 -0
  30. data/spec/support/laalaa/laalaa24.BMP +0 -0
  31. data/spec/support/laalaa/laalaa8.BMP +0 -0
  32. data/spec/support/ogro/Ogro.txt +132 -0
  33. data/spec/support/ogro/Ogrobase.pcx +0 -0
  34. data/spec/support/ogro/Weapon.md2 +0 -0
  35. data/spec/support/ogro/Weapon.pcx +0 -0
  36. data/spec/support/ogro/ogro.md2 +0 -0
  37. data/spec/support/ogro/ogro.png +0 -0
  38. data/spec/support/pilot/CC_attribution_licence.txt +68 -0
  39. data/spec/support/pilot/GNU_licence.txt +340 -0
  40. data/spec/support/pilot/Readme.txt +30 -0
  41. data/spec/support/pilot/body.md2 +0 -0
  42. data/spec/support/pilot/body.obj +9331 -0
  43. data/spec/support/pilot/head.md2 +0 -0
  44. data/spec/support/pilot/head.obj +6145 -0
  45. data/spec/support/pilot/pilot.md2 +0 -0
  46. data/spec/support/pilot/pilot_body.3ds +0 -0
  47. data/spec/support/pilot/pilot_body.jpg +0 -0
  48. data/spec/support/pilot/pilot_body.obj +2264 -0
  49. data/spec/support/pilot/pilot_head.3ds +0 -0
  50. data/spec/support/pilot/pilot_head.jpg +0 -0
  51. data/spec/support/pilot/pilot_head.obj +1970 -0
  52. data/spec/support/pknight/pknight.BMP +0 -0
  53. data/spec/support/pknight/pknight.PCX +0 -0
  54. data/spec/support/pknight/pknight.md2 +0 -0
  55. data/spec/support/pknight/pknight_weapon.PCX +0 -0
  56. data/spec/support/pknight/pknight_weapon.bmp +0 -0
  57. data/spec/support/pknight/pknight_weapon.md2 +0 -0
  58. data/spec/support/sodf8/Abarlith.pcx +0 -0
  59. data/spec/support/sodf8/SFOD8.txt +108 -0
  60. data/spec/support/sodf8/Weapon.PCX +0 -0
  61. data/spec/support/sodf8/Weapon.md2 +0 -0
  62. data/spec/support/sodf8/sodf8.md2 +0 -0
  63. metadata +167 -0
@@ -0,0 +1,63 @@
1
+ # This class is instantiated from the C extension. You shouldn't have to instantiate it directly.
2
+ #
3
+ # GL Commands are an optimization technique employed by MD2 files to improve render time. The
4
+ # MD2 file contains a span of bytes equal to the MD2::Header#gl_command_count. Those bytes in
5
+ # turn have the following format:
6
+ #
7
+ # 1. How many bytes follow for a single GL command. This is an integer, so the data need to be
8
+ # cast into an integer in order to be processed.
9
+ #
10
+ # This byte also indicates the render method for this GL command: if it's positive,
11
+ # this is a triangle strip; if it's negative, a triangle fan. If zero, this byte
12
+ # represents the end of the command list. Terminating bytes are silently omitted
13
+ # by this Ruby library.
14
+ # 2. The horizontal texture coordinate. This is a float, so the data needs to be cast into a
15
+ # float to be processed.
16
+ # 3. The vertical texture coordinate. This is a float, so the data needs to be cast into a
17
+ # float to be processed.
18
+ # 4. The vertex index to be rendered. This is an integer, so the data needs to be cast into
19
+ # an integer to be processed.
20
+ #
21
+ # As the data are cast into the necessary types, the boundaries of any given command structure
22
+ # must be adjusted to match. I was not able to find a way to do this using pure Ruby, so the
23
+ # bulk of the above algorithm is implemented in this gem's C extension.
24
+ #
25
+ # This class is only instantiated after the fact, with the data already deserialized.
26
+ #
27
+ class MD2::Command
28
+ # A data structure containing a single #texture_s, #texture_t and #vertex_index.
29
+ class Segment
30
+ attr_reader :texture_s, :texture_t, :vertex_index
31
+ def initialize(s, t, index)
32
+ @texture_s, @texture_t, @vertex_index = s, t, index
33
+ end
34
+ end
35
+
36
+ # The type of command. This is equal to either :triangle_strip or :triangle_fan.
37
+ attr_reader :type
38
+
39
+ # an array of segments, each an instance of MD2::Command::Segment. Segments contain the vertex and texture data
40
+ # for this command.
41
+ attr_reader :segments
42
+
43
+ # Arguments are expected to be a single array with the following content:
44
+ # [ (:triangle_strip|:triangle_fan), *elements ]
45
+ #
46
+ # The remainder of the elements are expected to appear in this order:
47
+ # (s_coord, t_coord, vert_index)
48
+ #
49
+ # So, the elements are expected to be in groups of 3: the s and t texture coordinates (which are Floats),
50
+ # and the vertex index (which is a Fixnum).
51
+ #
52
+ # The array of args is expected to be a single, flat array -- the data should not be nested
53
+ # into other arrays.
54
+ #
55
+ def initialize(args)
56
+ @type = args.shift
57
+ @segments = []
58
+
59
+ 0.step(args.length-1, 3) do |index|
60
+ @segments << MD2::Command::Segment.new(args[index], args[index+1], args[index+2])
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,13 @@
1
+ module MD2::Errors
2
+ # Not raised directly: this is a superclass for all other MD2 errors.
3
+ class Error < ::StandardError
4
+ end
5
+
6
+ # Raised when the specified file is invalid: for instance, when it is not an MD2 file.
7
+ class InvalidFile < Error
8
+ end
9
+
10
+ # Raised when the file format version specified in the header is not what was expected.
11
+ class InvalidVersion < Error
12
+ end
13
+ end
@@ -0,0 +1,61 @@
1
+ class MD2::Frame
2
+ # Float[3] containing X, Y, Z scale values
3
+ attr_reader :scale
4
+
5
+ # Float[3] containing X, Y, Z translations
6
+ attr_reader :translation
7
+
8
+ # The name of this frame (string)
9
+ attr_reader :name
10
+
11
+ # The vertices for this frame.
12
+ attr_reader :vertices
13
+
14
+ # The indices of the normal vectors.
15
+ attr_reader :normal_indices
16
+
17
+ def reduce
18
+ {
19
+ :name => name,
20
+ :translation => @translation,
21
+ :scale => @scale,
22
+ :vertices => packed_vertices,
23
+ :normal_indices => normal_indices.flatten
24
+ }
25
+ end
26
+
27
+ def initialize(frame_data)
28
+ @scale = []
29
+ @translation = []
30
+ @vertices = []
31
+ @normal_indices = []
32
+
33
+ # 3 floats (scale), 3 floats (transl), 16 bytes (name), and variable num of unsigned chars (vertices)
34
+ frame_data = frame_data.unpack("f3f3a16C*")
35
+ 3.times { @scale << frame_data.shift }
36
+ 3.times { @translation << frame_data.shift }
37
+ @name = frame_data.shift.strip
38
+ while !frame_data.empty?
39
+ packed_vertex = MD2::Vertex.new(frame_data.shift, frame_data.shift, frame_data.shift)
40
+ @vertices << unpack_vertex_data(packed_vertex)
41
+ @normal_indices << frame_data.shift
42
+ end
43
+ end
44
+
45
+ private
46
+ def packed_vertices
47
+ vertices.collect do |vert|
48
+ [ ((vert[0] - @translation[0]) / @scale[0]).to_i,
49
+ ((vert[1] - @translation[1]) / @scale[1]).to_i,
50
+ ((vert[2] - @translation[2]) / @scale[2]).to_i ]
51
+ end.flatten
52
+ end
53
+
54
+ def unpack_vertex_data(packed_vertex)
55
+ 3.times do |i|
56
+ packed_vertex[i] = (packed_vertex[i] * @scale[i]) + @translation[i]
57
+ end
58
+
59
+ packed_vertex
60
+ end
61
+ end
@@ -0,0 +1,37 @@
1
+ class MD2::Header
2
+ # The length of an MD2 header is fixed.
3
+ LENGTH = 68
4
+
5
+ # The magic number that all MD2 headers start with. This is equal to "IDP2" in bytes.
6
+ MD2_IDENT = ((?2.ord<<24) + (?P.ord<<16) + (?D.ord<<8) + ?I.ord) # we use #ord because of Ruby 1.9
7
+
8
+ # The MD2 file format version. This is always 8.
9
+ MD2_VERSION = 8
10
+
11
+ attr_reader :skin_width, :skin_height, :frame_size, :skin_count, :vertex_count,
12
+ :texture_coord_count, :triangle_count, :gl_command_count, :frame_count,
13
+ :skin_name_offset, :texture_coord_offset, :triangle_offset, :frame_data_offset,
14
+ :gl_command_offset, :eof_offset
15
+
16
+ def initialize(file)
17
+ header = file.sysread(LENGTH).unpack("i17")
18
+ raise MD2::Errors::InvalidFile, "Header identifier did not match" unless header.shift == MD2_IDENT
19
+ raise MD2::Errors::InvalidVersion, "File format version mismatch" unless header.shift == MD2_VERSION
20
+
21
+ @skin_width = header.shift
22
+ @skin_height = header.shift
23
+ @frame_size = header.shift
24
+ @skin_count = header.shift
25
+ @vertex_count = header.shift
26
+ @texture_coord_count = header.shift
27
+ @triangle_count = header.shift
28
+ @gl_command_count = header.shift
29
+ @frame_count = header.shift
30
+ @skin_name_offset = header.shift
31
+ @texture_coord_offset = header.shift
32
+ @triangle_offset = header.shift
33
+ @frame_data_offset = header.shift
34
+ @gl_command_offset = header.shift
35
+ @eof_offset = header.shift
36
+ end
37
+ end
@@ -0,0 +1,81 @@
1
+ class MD2
2
+ # For your convenience: NORMALS is an array of arrays which contain X, Y and Z float values.
3
+ #
4
+ # This is the same for every MD2 file, and is referenced by the normal indices within the model data.
5
+ #
6
+ # You can get this data with simply:
7
+ #
8
+ # MD2::Normals[index]
9
+ #
10
+ # or you can use its longer variant:
11
+ #
12
+ # MD2::Normals::NORMALS[index].
13
+ #
14
+ class Normals
15
+ class << self
16
+ delegate :[], :[]=, :to => :_normals
17
+
18
+ def _normals #:nodoc:
19
+ MD2::Normals::NORMALS
20
+ end
21
+ end
22
+
23
+
24
+ NORMALS = [
25
+ [-0.525731, 0.000000, 0.850651], [-0.442863, 0.238856, 0.864188], [-0.295242, 0.000000, 0.955423],
26
+ [-0.309017, 0.500000, 0.809017], [-0.162460, 0.262866, 0.951056], [ 0.000000, 0.000000, 1.000000],
27
+ [ 0.000000, 0.850651, 0.525731], [-0.147621, 0.716567, 0.681718], [ 0.147621, 0.716567, 0.681718],
28
+ [ 0.000000, 0.525731, 0.850651], [ 0.309017, 0.500000, 0.809017], [ 0.525731, 0.000000, 0.850651],
29
+ [ 0.295242, 0.000000, 0.955423], [ 0.442863, 0.238856, 0.864188], [ 0.162460, 0.262866, 0.951056],
30
+ [-0.681718, 0.147621, 0.716567], [-0.809017, 0.309017, 0.500000], [-0.587785, 0.425325, 0.688191],
31
+ [-0.850651, 0.525731, 0.000000], [-0.864188, 0.442863, 0.238856], [-0.716567, 0.681718, 0.147621],
32
+ [-0.688191, 0.587785, 0.425325], [-0.500000, 0.809017, 0.309017], [-0.238856, 0.864188, 0.442863],
33
+ [-0.425325, 0.688191, 0.587785], [-0.716567, 0.681718, -0.147621], [-0.500000, 0.809017, -0.309017],
34
+ [-0.525731, 0.850651, 0.000000], [ 0.000000, 0.850651, -0.525731], [-0.238856, 0.864188, -0.442863],
35
+ [ 0.000000, 0.955423, -0.295242], [-0.262866, 0.951056, -0.162460], [ 0.000000, 1.000000, 0.000000],
36
+ [ 0.000000, 0.955423, 0.295242], [-0.262866, 0.951056, 0.162460], [ 0.238856, 0.864188, 0.442863],
37
+ [ 0.262866, 0.951056, 0.162460], [ 0.500000, 0.809017, 0.309017], [ 0.238856, 0.864188, -0.442863],
38
+ [ 0.262866, 0.951056, -0.162460], [ 0.500000, 0.809017, -0.309017], [ 0.850651, 0.525731, 0.000000],
39
+ [ 0.716567, 0.681718, 0.147621], [ 0.716567, 0.681718, -0.147621], [ 0.525731, 0.850651, 0.000000],
40
+ [ 0.425325, 0.688191, 0.587785], [ 0.864188, 0.442863, 0.238856], [ 0.688191, 0.587785, 0.425325],
41
+ [ 0.809017, 0.309017, 0.500000], [ 0.681718, 0.147621, 0.716567], [ 0.587785, 0.425325, 0.688191],
42
+ [ 0.955423, 0.295242, 0.000000], [ 1.000000, 0.000000, 0.000000], [ 0.951056, 0.162460, 0.262866],
43
+ [ 0.850651, -0.525731, 0.000000], [ 0.955423, -0.295242, 0.000000], [ 0.864188, -0.442863, 0.238856],
44
+ [ 0.951056, -0.162460, 0.262866], [ 0.809017, -0.309017, 0.500000], [ 0.681718, -0.147621, 0.716567],
45
+ [ 0.850651, 0.000000, 0.525731], [ 0.864188, 0.442863, -0.238856], [ 0.809017, 0.309017, -0.500000],
46
+ [ 0.951056, 0.162460, -0.262866], [ 0.525731, 0.000000, -0.850651], [ 0.681718, 0.147621, -0.716567],
47
+ [ 0.681718, -0.147621, -0.716567], [ 0.850651, 0.000000, -0.525731], [ 0.809017, -0.309017, -0.500000],
48
+ [ 0.864188, -0.442863, -0.238856], [ 0.951056, -0.162460, -0.262866], [ 0.147621, 0.716567, -0.681718],
49
+ [ 0.309017, 0.500000, -0.809017], [ 0.425325, 0.688191, -0.587785], [ 0.442863, 0.238856, -0.864188],
50
+ [ 0.587785, 0.425325, -0.688191], [ 0.688191, 0.587785, -0.425325], [-0.147621, 0.716567, -0.681718],
51
+ [-0.309017, 0.500000, -0.809017], [ 0.000000, 0.525731, -0.850651], [-0.525731, 0.000000, -0.850651],
52
+ [-0.442863, 0.238856, -0.864188], [-0.295242, 0.000000, -0.955423], [-0.162460, 0.262866, -0.951056],
53
+ [ 0.000000, 0.000000, -1.000000], [ 0.295242, 0.000000, -0.955423], [ 0.162460, 0.262866, -0.951056],
54
+ [-0.442863, -0.238856, -0.864188], [-0.309017, -0.500000, -0.809017], [-0.162460, -0.262866, -0.951056],
55
+ [ 0.000000, -0.850651, -0.525731], [-0.147621, -0.716567, -0.681718], [ 0.147621, -0.716567, -0.681718],
56
+ [ 0.000000, -0.525731, -0.850651], [ 0.309017, -0.500000, -0.809017], [ 0.442863, -0.238856, -0.864188],
57
+ [ 0.162460, -0.262866, -0.951056], [ 0.238856, -0.864188, -0.442863], [ 0.500000, -0.809017, -0.309017],
58
+ [ 0.425325, -0.688191, -0.587785], [ 0.716567, -0.681718, -0.147621], [ 0.688191, -0.587785, -0.425325],
59
+ [ 0.587785, -0.425325, -0.688191], [ 0.000000, -0.955423, -0.295242], [ 0.000000, -1.000000, 0.000000],
60
+ [ 0.262866, -0.951056, -0.162460], [ 0.000000, -0.850651, 0.525731], [ 0.000000, -0.955423, 0.295242],
61
+ [ 0.238856, -0.864188, 0.442863], [ 0.262866, -0.951056, 0.162460], [ 0.500000, -0.809017, 0.309017],
62
+ [ 0.716567, -0.681718, 0.147621], [ 0.525731, -0.850651, 0.000000], [-0.238856, -0.864188, -0.442863],
63
+ [-0.500000, -0.809017, -0.309017], [-0.262866, -0.951056, -0.162460], [-0.850651, -0.525731, 0.000000],
64
+ [-0.716567, -0.681718, -0.147621], [-0.716567, -0.681718, 0.147621], [-0.525731, -0.850651, 0.000000],
65
+ [-0.500000, -0.809017, 0.309017], [-0.238856, -0.864188, 0.442863], [-0.262866, -0.951056, 0.162460],
66
+ [-0.864188, -0.442863, 0.238856], [-0.809017, -0.309017, 0.500000], [-0.688191, -0.587785, 0.425325],
67
+ [-0.681718, -0.147621, 0.716567], [-0.442863, -0.238856, 0.864188], [-0.587785, -0.425325, 0.688191],
68
+ [-0.309017, -0.500000, 0.809017], [-0.147621, -0.716567, 0.681718], [-0.425325, -0.688191, 0.587785],
69
+ [-0.162460, -0.262866, 0.951056], [ 0.442863, -0.238856, 0.864188], [ 0.162460, -0.262866, 0.951056],
70
+ [ 0.309017, -0.500000, 0.809017], [ 0.147621, -0.716567, 0.681718], [ 0.000000, -0.525731, 0.850651],
71
+ [ 0.425325, -0.688191, 0.587785], [ 0.587785, -0.425325, 0.688191], [ 0.688191, -0.587785, 0.425325],
72
+ [-0.955423, 0.295242, 0.000000], [-0.951056, 0.162460, 0.262866], [-1.000000, 0.000000, 0.000000],
73
+ [-0.850651, 0.000000, 0.525731], [-0.955423, -0.295242, 0.000000], [-0.951056, -0.162460, 0.262866],
74
+ [-0.864188, 0.442863, -0.238856], [-0.951056, 0.162460, -0.262866], [-0.809017, 0.309017, -0.500000],
75
+ [-0.864188, -0.442863, -0.238856], [-0.951056, -0.162460, -0.262866], [-0.809017, -0.309017, -0.500000],
76
+ [-0.681718, 0.147621, -0.716567], [-0.681718, -0.147621, -0.716567], [-0.850651, 0.000000, -0.525731],
77
+ [-0.688191, 0.587785, -0.425325], [-0.587785, 0.425325, -0.688191], [-0.425325, 0.688191, -0.587785],
78
+ [-0.425325, -0.688191, -0.587785], [-0.587785, -0.425325, -0.688191], [-0.688191, -0.587785, -0.425325]
79
+ ].collect { |c| c.freeze }.freeze
80
+ end
81
+ end
@@ -0,0 +1,9 @@
1
+ class MD2::Triangle
2
+ attr_reader :vertex_indices, :texcoord_indices
3
+
4
+ def initialize(data)
5
+ data = data.unpack("s6")
6
+ @vertex_indices = [data[0], data[1], data[2]]
7
+ @texcoord_indices = [data[3], data[4], data[5]]
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ class MD2::Vertex < Array
2
+ def initialize(x, y, z)
3
+ super()
4
+ raise ArgumentError, "x is nil" if x.nil?
5
+ raise ArgumentError, "y is nil" if y.nil?
6
+ raise ArgumentError, "z is nil" if z.nil?
7
+ self << x << y << z
8
+ end
9
+
10
+ def x
11
+ self[0]
12
+ end
13
+
14
+ def y
15
+ self[1]
16
+ end
17
+
18
+ def z
19
+ self[2]
20
+ end
21
+
22
+ def x=(x)
23
+ self[0] = x
24
+ end
25
+
26
+ def y=(y)
27
+ self[1] = y
28
+ end
29
+
30
+ def z=(z)
31
+ self[2] = z
32
+ end
33
+ end
@@ -0,0 +1,117 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{md2}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Colin MacKenzie IV"]
12
+ s.date = %q{2010-10-28}
13
+ s.default_executable = %q{md2_to_json}
14
+ s.description = %q{A Ruby library for loading MD2 3D model files.}
15
+ s.email = %q{sinisterchipmunk@gmail.com}
16
+ s.executables = ["md2_to_json"]
17
+ s.extensions = ["ext/md2/extconf.rb"]
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README.rdoc"
21
+ ]
22
+ s.files = [
23
+ ".document",
24
+ ".gitignore",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "bin/md2_to_json",
30
+ "ext/md2/extconf.rb",
31
+ "ext/md2/md2.c",
32
+ "lib/md2.rb",
33
+ "lib/md2/command.rb",
34
+ "lib/md2/errors.rb",
35
+ "lib/md2/frame.rb",
36
+ "lib/md2/header.rb",
37
+ "lib/md2/normals.rb",
38
+ "lib/md2/triangle.rb",
39
+ "lib/md2/vertex.rb",
40
+ "md2.gemspec",
41
+ "spec/lib/md2/frame_spec.rb",
42
+ "spec/lib/md2/header_spec.rb",
43
+ "spec/lib/md2_spec.rb",
44
+ "spec/spec_helper.rb",
45
+ "spec/support/crafty/Crafty.BMP",
46
+ "spec/support/crafty/Crafty.pcx",
47
+ "spec/support/crafty/Crafty.txt",
48
+ "spec/support/crafty/Weapon.md2",
49
+ "spec/support/crafty/Weapon.pcx",
50
+ "spec/support/crafty/crafty.md2",
51
+ "spec/support/laalaa/laalaa.md2",
52
+ "spec/support/laalaa/laalaa24.BMP",
53
+ "spec/support/laalaa/laalaa8.BMP",
54
+ "spec/support/ogro/Ogro.txt",
55
+ "spec/support/ogro/Ogrobase.pcx",
56
+ "spec/support/ogro/Weapon.md2",
57
+ "spec/support/ogro/Weapon.pcx",
58
+ "spec/support/ogro/ogro.md2",
59
+ "spec/support/ogro/ogro.png",
60
+ "spec/support/pilot/CC_attribution_licence.txt",
61
+ "spec/support/pilot/GNU_licence.txt",
62
+ "spec/support/pilot/Readme.txt",
63
+ "spec/support/pilot/body.md2",
64
+ "spec/support/pilot/body.obj",
65
+ "spec/support/pilot/head.md2",
66
+ "spec/support/pilot/head.obj",
67
+ "spec/support/pilot/pilot.md2",
68
+ "spec/support/pilot/pilot_body.3ds",
69
+ "spec/support/pilot/pilot_body.jpg",
70
+ "spec/support/pilot/pilot_body.obj",
71
+ "spec/support/pilot/pilot_head.3ds",
72
+ "spec/support/pilot/pilot_head.jpg",
73
+ "spec/support/pilot/pilot_head.obj",
74
+ "spec/support/pknight/pknight.BMP",
75
+ "spec/support/pknight/pknight.PCX",
76
+ "spec/support/pknight/pknight.md2",
77
+ "spec/support/pknight/pknight_weapon.PCX",
78
+ "spec/support/pknight/pknight_weapon.bmp",
79
+ "spec/support/pknight/pknight_weapon.md2",
80
+ "spec/support/sodf8/Abarlith.pcx",
81
+ "spec/support/sodf8/SFOD8.txt",
82
+ "spec/support/sodf8/Weapon.PCX",
83
+ "spec/support/sodf8/Weapon.md2",
84
+ "spec/support/sodf8/sodf8.md2"
85
+ ]
86
+ s.homepage = %q{http://thoughtsincomputation.com}
87
+ s.rdoc_options = ["--charset=UTF-8"]
88
+ s.require_paths = ["lib"]
89
+ s.rubygems_version = %q{1.3.6}
90
+ s.summary = %q{A Ruby library for loading MD2 3D model files.}
91
+ s.test_files = [
92
+ "spec/lib/md2/frame_spec.rb",
93
+ "spec/lib/md2/header_spec.rb",
94
+ "spec/lib/md2_spec.rb",
95
+ "spec/spec_helper.rb"
96
+ ]
97
+
98
+ if s.respond_to? :specification_version then
99
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
100
+ s.specification_version = 3
101
+
102
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
103
+ s.add_runtime_dependency(%q<sizes>, [">= 1.0"])
104
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.5"])
105
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
106
+ else
107
+ s.add_dependency(%q<sizes>, [">= 1.0"])
108
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
109
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
110
+ end
111
+ else
112
+ s.add_dependency(%q<sizes>, [">= 1.0"])
113
+ s.add_dependency(%q<activesupport>, [">= 2.3.5"])
114
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
115
+ end
116
+ end
117
+
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe MD2 do
4
+ subject { MD2.new(md2_file("pilot")) }
5
+
6
+ it "should have frames.first.vertices.size == header.vertex_count" do
7
+ subject.frames.first.vertices.size.should == subject.header.vertex_count
8
+ end
9
+
10
+ it "should not contain null characters" do
11
+ subject.frames.first.name.should_not =~ /#{Regexp::escape ?\0.chr}/
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe MD2::Header do
4
+ context "with invalid content" do
5
+ subject { MD2::Header.new(mock_io("this is invalid "*10)) }
6
+
7
+ it "should raise MD2::Errors::InvalidFile" do
8
+ proc { subject }.should raise_error(MD2::Errors::InvalidFile)
9
+ end
10
+ end
11
+
12
+ context "with valid ID" do
13
+ context "and invalid version" do
14
+ subject { MD2::Header.new(mock_io("IDP2" + ("this is invalid"*10))) }
15
+
16
+ it "should raise MD2::Errors::InvalidVersion" do
17
+ proc { subject }.should raise_error(MD2::Errors::InvalidVersion)
18
+ end
19
+ end
20
+ end
21
+ end