Class: RAGE::Mesh

Inherits:
Object
  • Object
show all
Defined in:
lib/rage/mesh.rb

Overview

3D mesh to be displayed on the screen. Contains geometry and visual properties. Currently implements certain parts of the X3D graphics schema. en.wikipedia.org/wiki/X3D

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Mesh

Create new mesh from raw X3D mesh



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/rage/mesh.rb', line 30

def initialize(data)
   # set default attributes
   @op_translation =  [0,0,0]
   @op_scale       =  [1,1,1]

   # load the x3d xsd schema and classes if not already done so
   unless defined? @@x3d_schema
     @@x3d_schema = RXSD::Parser.parse_xsd :uri => 'http://www.web3d.org/specifications/x3d-3.0.xsd' # TODO allow location which this is pulled from to be configured
     @@x3d_schema_classes = @@x3d_schema.to :ruby_classes
   end

   # load the scene from the x3d schema instance
   objs = RXSD::Parser.parse_xml(:raw => data).to(:ruby_objects, :schema => @@x3d_schema)
   @scene = objs[0].scene

   # FIXME get all transformations (and groups of) under scene
   @tf = @scene.collision.transform
   @translation = @tf.translation.to_xa :type => XSDFloat
   @scale       = @tf.scale.to_xa :type => XSDFloat
   #diffuse     = tf.shape.appearance.material.diffuse_color.split.collect { |c| c.to_f }
   #specular    = tf.shape.appearance.material.specular_color.split.collect { |c| c.to_f }
   #emissive    = tf.shape.appearance.material.emissive_color.split.collect { |c| c.to_f }
   @coord_index  = @tf.shape.indexed_face_set.coord_index.
                                   to_xa(:type => String, :delim => ",").
                                   collect { |coords| a = coords.to_xa(:type => XSDInteger); a[0...a.size-1]}.flatten # cut off the last -1
   @coord_point  = @tf.shape.indexed_face_set.coordinate.point.
                                   to_xa(:type => String, :delim => ",").
                                   collect { |coords| coords.to_xa :type => XSDFloat }.flatten
end

Instance Attribute Details

#op_rotationObject

Optional transformation params, set these to transformations to be factored in if needed



20
21
22
# File 'lib/rage/mesh.rb', line 20

def op_rotation
  @op_rotation
end

#op_scaleObject

Optional transformation params, set these to transformations to be factored in if needed



20
21
22
# File 'lib/rage/mesh.rb', line 20

def op_scale
  @op_scale
end

#op_translationObject

Optional transformation params, set these to transformations to be factored in if needed



20
21
22
# File 'lib/rage/mesh.rb', line 20

def op_translation
  @op_translation
end

Instance Method Details

#boundariesObject

Return mesh boundaries. This is generated by determining the maxima/minima coordinate points. Return value is an array of six values as follows

max_x, max_y, max_z, min_x, min_y, min_z


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rage/mesh.rb', line 98

def boundaries
   centerx, centery, centerz = *center
   max_x = max_y = max_z = min_x = min_y = min_z = 0
   @coord_point.each_index {  |cpi|
      if cpi % 3 == 0
        adjx = centerx + @coord_point[cpi]
        if  adjx > max_x
           max_x = adjx
        elsif adjx < min_x
           min_x = adjx
        end
      elsif cpi % 3 == 1 
        adjy = centery + @coord_point[cpi]
        if adjy > max_y
           max_y = adjy
        elsif adjy < min_y
           min_y = adjy
        end
      else
        adjz = centerz + @coord_point[cpi]
        if adjz > max_z
           max_z = adjz
        elsif adjz < min_z
           min_z = adjz
        end
      end
   }
   return max_x, max_y, max_z, min_x, min_y, min_z
end

#centerObject

Return center point of mesh from mesh translation provided in mesh and op_translation



82
83
84
85
86
# File 'lib/rage/mesh.rb', line 82

def center
   return @op_translation[0] + @translation[0],
          @op_translation[1] + @translation[1],
          @op_translation[2] + @translation[2]
end

#coordinatesObject

Return current location coordinates associated w/ the mesh



75
76
77
# File 'lib/rage/mesh.rb', line 75

def coordinates
  [@location.x, @location.y, @location.z]
end

#drawObject

Invoked during draw cycle to draw mesh



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/rage/mesh.rb', line 130

def draw
   # FIXME mesh material
   #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_DIFFUSE,  diffuse)
   #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_SPECULAR, specular)
   #Gl.glMaterial(Gl::GL_FRONT, Gl::GL_EMISSIVE, emissive)

   # translate coordinate system to center position of mesh
   Gl.glTranslatef(*center)

   # scale as specified 
   Gl.glScalef(*scale)

   # FIXME rotate according to mesh and optional params

   # draw mesh
   Gl.glEnableClientState(Gl::GL_VERTEX_ARRAY);
   Gl.glVertexPointer(3, Gl::GL_FLOAT, 0, @coord_point);
   Gl.glDrawElements(Gl::GL_QUADS, @coord_index.size, Gl::GL_UNSIGNED_INT, @coord_index);
   Gl.glDisableClientState(Gl::GL_VERTEX_ARRAY);
end

#scaleObject

Return factor which mesh should scale to



89
90
91
92
93
# File 'lib/rage/mesh.rb', line 89

def scale
   return @scale[0] * @op_scale[0],
          @scale[1] * @op_scale[1],
          @scale[2] * @op_scale[2]
end

#show_at(args = {}) ⇒ Object

Create location w/ specified args, associated mesh w/ it and add it to the LocationsManager



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/rage/mesh.rb', line 61

def show_at(args = {})
  # XXX not a huge fan of storing location interally,
  # but this is best way to do this for now
  if ! defined? @location
    args[:mesh] = self
    @location = Location.new(args)
    LocationsManager.instance.add @location
  else
    @location.update args
  end
  return @location
end