disp3D 0.2.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/Gemfile +1 -1
  2. data/README.md +56 -0
  3. data/VERSION +1 -1
  4. data/disp3D.gemspec +24 -20
  5. data/example/stl_viewer/document_ctrl.rb +2 -2
  6. data/example/stl_viewer/qt_widget_controller.rb +3 -7
  7. data/example/tutorial/03_CameraScene.rb +5 -5
  8. data/example/tutorial/04_Qt.rb +4 -4
  9. data/example/tutorial/05_Pick.rb +13 -13
  10. data/example/tutorial/06_FileParser.rb +3 -3
  11. data/example/tutorial/07_SceneGraph.rb +16 -4
  12. data/example/tutorial/08_SceneGraph2.rb +16 -15
  13. data/example/tutorial/09_Texture.rb +28 -0
  14. data/example/tutorial/10_Animation.rb +27 -0
  15. data/example/tutorial/10_AnimationQt.rb +53 -0
  16. data/example/tutorial/11_MultiView.rb +41 -0
  17. data/example/tutorial/12_Light.rb +65 -0
  18. data/example/tutorial/13_RectPick.rb +38 -0
  19. data/example/tutorial/14_LineRubberband.rb +43 -0
  20. data/example/{test → tutorial}/data/test.png +0 -0
  21. data/example/{test → tutorial}/data/test2.jpg +0 -0
  22. data/lib/camera.rb +8 -0
  23. data/lib/compass.rb +21 -14
  24. data/lib/disp3D.rb +3 -0
  25. data/lib/gl_view.rb +70 -40
  26. data/lib/glut_window.rb +24 -18
  27. data/lib/light.rb +35 -21
  28. data/lib/manipulator.rb +0 -7
  29. data/lib/node/node.rb +100 -105
  30. data/lib/node/node_arrows.rb +1 -1
  31. data/lib/node/node_collection.rb +63 -17
  32. data/lib/node/node_cone.rb +49 -0
  33. data/lib/node/node_coord.rb +26 -11
  34. data/lib/node/node_leaf.rb +17 -11
  35. data/lib/node/node_lines.rb +1 -1
  36. data/lib/node/node_points.rb +2 -1
  37. data/lib/node/node_polylines.rb +1 -1
  38. data/lib/node/node_rectangle.rb +9 -4
  39. data/lib/node/node_sphere.rb +28 -0
  40. data/lib/node/node_tea_pod.rb +4 -4
  41. data/lib/node/node_text.rb +2 -2
  42. data/lib/node/node_tris.rb +1 -1
  43. data/lib/node/node_workplane.rb +33 -1
  44. data/lib/picker.rb +157 -3
  45. data/lib/qt_widget_gl.rb +24 -11
  46. data/lib/scene_graph.rb +3 -3
  47. data/test/node/test_node.rb +230 -0
  48. data/test/node/test_node_collection.rb +99 -79
  49. data/test/test_picker.rb +6 -6
  50. metadata +28 -24
  51. data/README.rdoc +0 -63
  52. data/example/test/capture_test.rb +0 -16
  53. data/example/test/dsl_test.rb +0 -46
  54. data/example/test/texture_test.rb +0 -39
  55. data/test/data/binary_test.stl +0 -0
  56. data/test/data/bunny-flatfoot.stl +0 -0
data/lib/glut_window.rb CHANGED
@@ -15,7 +15,7 @@ module Disp3D
15
15
 
16
16
  GLUT.MouseFunc(method(:mouse).to_proc())
17
17
  GLUT.MotionFunc(method(:motion).to_proc())
18
- GLUT.PassiveMotionFunc(method(:passive_motion).to_proc())
18
+ GLUT.PassiveMotionFunc(method(:motion).to_proc())
19
19
  super(width, height)
20
20
  end
21
21
 
@@ -28,34 +28,40 @@ module Disp3D
28
28
  GLUT.SwapBuffers
29
29
  end
30
30
 
31
- def reshape(w,h)
32
- @camera.reshape(w,h)
31
+ def idle_process(wait_msec = nil, &block)
32
+ if(!wait_msec.nil?)
33
+ new_block = lambda do
34
+ @lasttime = Time.now if(@lasttime.nil?)
35
+ interval = Time.now - @lasttime
36
+ next if( interval < wait_msec/1000.0)
37
+ yield
38
+ @lasttime = Time.now
39
+ end
40
+ GLUT.IdleFunc(new_block)
41
+ else
42
+ GLUT.IdleFunc(block)
43
+ end
33
44
  end
34
45
 
46
+ def start
47
+ fit
48
+ GLUT.MainLoop()
49
+ end
50
+
51
+ private
35
52
  def mouse(button,state,x,y)
36
53
  if(state == GLUT::GLUT_UP)
37
- @mouse_release_proc.call(self, button, x, y) if( @mouse_release_proc != nil)
54
+ mouse_release_process(button, x, y)
38
55
  elsif(state == GLUT::GLUT_DOWN)
39
- @mouse_press_proc.call(self, button, x, y) if( @mouse_press_proc != nil)
56
+ mouse_press_process(button, x, y)
40
57
  end
41
- @manipulator.mouse(button,state,x,y)
42
58
  end
43
59
 
44
60
  def motion(x,y)
45
- @mouse_move_proc.call(self, x,y) if( @mouse_move_proc != nil)
46
- update = @manipulator.motion(x,y)
47
- if(update)
61
+ need_update = mouse_move_process(x, y)
62
+ if(need_update)
48
63
  GLUT.PostRedisplay()
49
64
  end
50
65
  end
51
-
52
- def passive_motion(x,y)
53
- @mouse_move_proc.call(self, x,y) if( @mouse_move_proc != nil)
54
- end
55
-
56
- def start
57
- fit
58
- GLUT.MainLoop()
59
- end
60
66
  end
61
67
  end
data/lib/light.rb CHANGED
@@ -2,38 +2,21 @@ require 'disp3D'
2
2
 
3
3
  module Disp3D
4
4
  class Light
5
- def gl_display()
6
- idx = 0
7
- GL.Enable(GL::GL_LIGHTING)
8
- all_disable = true
9
- @enable.each do | enable |
10
- if(enable)
11
- GL.Enable( @light_id[idx])
12
- GL.Lightfv( @light_id[idx], GL::GL_POSITION, @position[idx] )
13
- GL.Lightfv( @light_id[idx], GL::GL_DIFFUSE, @deffuse[idx] )
14
- GL.Lightfv( @light_id[idx], GL::GL_AMBIENT, @ambient[idx] )
15
- GL.Lightfv( @light_id[idx], GL::GL_SPECULAR, @specular[idx] )
16
- all_disable = false
17
- end
18
- end
19
- if(all_disable)
20
- GL.Enable(@light_id[0])
21
- end
22
- end
23
-
24
5
  def initialize()
25
6
  @diffuse_default = [0.7, 0.7, 0.7, 1]
26
7
  @ambient_default = [0.2, 0.2, 0.2, 1]
27
8
  @specular_default = [1, 1, 1, 1]
28
- @position_default = [0.0, 0.0, 1.0, 0.0]
9
+ @position_default = Vector3.new(0.0, 0.0, 1.0)
10
+ @spot_direction_default = Vector3.new(0.0, 0.0, -1.0)
29
11
 
30
12
  light_count = 8 # openGL spec
31
13
 
32
14
  @enable = [false, false, false, false, false, false, false, false]
33
- @deffuse = Array.new(light_count, @diffuse_default)
15
+ @diffuse = Array.new(light_count, @diffuse_default)
34
16
  @ambient = Array.new(light_count, @ambient_default)
35
17
  @specular = Array.new(light_count, @specular_default)
36
18
  @position = Array.new(light_count, @position_default)
19
+ @spot_direction = Array.new(light_count, @spot_direction_default)
37
20
  @light_id = Array.new(light_count)
38
21
  @light_id[0] = GL::GL_LIGHT0
39
22
  @light_id[1] = GL::GL_LIGHT1
@@ -45,5 +28,36 @@ module Disp3D
45
28
  @light_id[7] = GL::GL_LIGHT7
46
29
  end
47
30
 
31
+ def gl_display()
32
+ GL.Enable(GL::GL_LIGHTING)
33
+ @enable.each_with_index do | enable, idx |
34
+ if(enable)
35
+ GL.Enable( @light_id[idx])
36
+ GL.Lightfv( @light_id[idx], GL::POSITION, [@position[idx].x,@position[idx].y,@position[idx].z] )
37
+ GL.Lightfv( @light_id[idx], GL::SPOT_DIRECTION, [@spot_direction[idx].x,@spot_direction[idx].y,@spot_direction[idx].z] )
38
+ GL.Lightfv( @light_id[idx], GL::DIFFUSE, @diffuse[idx] )
39
+ GL.Lightfv( @light_id[idx], GL::AMBIENT, @ambient[idx] )
40
+ GL.Lightfv( @light_id[idx], GL::SPECULAR, @specular[idx] )
41
+ end
42
+ end
43
+ if(!@enable.include?(true))
44
+ GL.Enable(@light_id[0])
45
+ end
46
+ end
47
+
48
+ def open(&block)
49
+ self.instance_eval(&block)
50
+ end
51
+
52
+ private
53
+ def set(hash)
54
+ Util3D.check_key_arg(hash, :id)
55
+ target_idx = hash[:id]
56
+ hash.each do | key, value |
57
+ next if( key == :id)
58
+ target_ary = eval "@#{key.to_s}"
59
+ target_ary[target_idx]=value
60
+ end
61
+ end
48
62
  end
49
63
  end
data/lib/manipulator.rb CHANGED
@@ -1,4 +1,3 @@
1
- # -*- coding: cp932 -*-
2
1
  require 'disp3D'
3
2
 
4
3
  include GMath3D
@@ -15,8 +14,6 @@ module Disp3D
15
14
  @scalling = false
16
15
  @translating = false
17
16
  @trackball_size = 0.8
18
-
19
- @compass = Compass.new(camera)
20
17
  end
21
18
 
22
19
  def centering(scene_graph)
@@ -97,10 +94,6 @@ module Disp3D
97
94
  return false
98
95
  end
99
96
 
100
- def gl_display_compass
101
- @compass.gl_display()
102
- end
103
-
104
97
  private
105
98
  def set_clicked_point_as_rotation_center(x,y)
106
99
  results = @picker.pick(x,y)
data/lib/node/node.rb CHANGED
@@ -1,90 +1,115 @@
1
1
  require 'disp3D'
2
2
 
3
+ class Class
4
+ # use this instead of attr_accessor.
5
+ # if attribute is changed call Node#update
6
+ def attr_for_disp(attribute)
7
+ define_method "#{attribute}=" do |value|
8
+ instance_variable_set("@#{attribute}", value)
9
+ update_for_display
10
+ end
11
+ define_method attribute do
12
+ instance_variable_get "@#{attribute}"
13
+ end
14
+ end
15
+ end
16
+
3
17
  module Disp3D
4
18
  class Node
5
- attr_accessor :pre_translate # GMath3D::Vector3
6
- attr_accessor :rotate # GMath3D::Quat
7
- attr_accessor :post_translate # GMath3D::Vector3
19
+ attr_for_disp :pre_translate # GMath3D::Vector3
20
+ attr_for_disp :rotate # GMath3D::Quat
21
+ attr_for_disp :post_translate # GMath3D::Vector3
8
22
 
9
23
  attr_reader :name
10
24
  attr_reader :instance_id
11
-
12
- attr_accessor :parents # Array of Node
25
+ attr_reader :parents # Array of Node
13
26
 
14
27
  def initialize(name = nil)
15
28
  Util3D.check_arg_type(Symbol, name, true)
16
-
17
- @name = name
18
- @translate = nil
19
- @rotate = nil
20
29
  @parents = []
21
30
  @instance_id = gen_instance_id()
22
- Node.add_to_node_name_db(self) if(!name.nil?)
31
+ @name = name
32
+ NodeDB.add(self)
23
33
  end
24
34
 
25
- # path id DB
26
- def self.init_path_db
27
- @path_db = Hash.new
35
+ def pre_draw
36
+ GL.PushMatrix()
37
+ GL.Translate(pre_translate.x, pre_translate.y, pre_translate.z) if(@pre_translate)
38
+ GL.MultMatrix(@rotate.to_array) if(@rotate)
39
+ GL.Translate(post_translate.x, post_translate.y, post_translate.z) if(@post_translate)
28
40
  end
29
41
 
30
- def self.add_to_path_db(path_id, node)
31
- return @path_db[path_id] = node
42
+ def post_draw
43
+ GL.PopMatrix()
32
44
  end
33
45
 
34
- def self.find_node_by_path_id(path_id)
35
- return @path_db[path_id]
46
+ def ancestors
47
+ rtn_ancestors_ary = []
48
+ return ancestors_inner(rtn_ancestors_ary)
36
49
  end
37
50
 
38
- # node name DB
39
- def self.add_to_node_name_db(node)
40
- Util3D.check_arg_type(Node, node)
41
- @node_db ||= Hash.new()
42
- key = node.name
43
- if(!@node_db.key?(key))
44
- @node_db[key] = node
45
- elsif(@node_db[key].kind_of?(Node))
46
- @node_db[key] = [@node_db[key], node]
47
- elsif(@node_db[key].kind_of?(Array))
48
- @node_db[key].push(node)
51
+ protected
52
+ def create(hash)
53
+ Util3D.check_key_arg(hash, :type)
54
+ geom_arg = hash[:geom]
55
+ name_arg = hash[:name]
56
+ clazz = eval "Node" + hash[:type].to_s
57
+ # node leaf constractor need 2 args
58
+ if( clazz < Disp3D::NodeLeaf )
59
+ new_node = clazz.new(geom_arg, name_arg)
60
+ elsif( clazz <= Disp3D::NodeCollection )
61
+ new_node = clazz.new(name_arg)
49
62
  else
50
63
  raise
51
64
  end
65
+ hash.delete(:geom)
66
+ hash.delete(:type)
67
+ hash.delete(:name)
68
+ new_node.update(hash)
69
+ return new_node
52
70
  end
53
71
 
54
- def self.find_node_by_name(node_name)
55
- Util3D.check_arg_type(Symbol, node_name)
56
- return @node_db[node_name]
57
- end
58
-
59
- def self.delete_from_node_name_db_by_node(node)
60
- node_name = node.name
61
- if(!node_name.nil?)
62
- entry = find_node_by_name(node_name)
63
- if(entry == node)
64
- @node_db[node_name] = nil
65
- elsif(entry.kind_of?(Array))
66
- entry.reject!{|item| item == node}
72
+ # cannnot contains key :type and :name. they cannot be set
73
+ def update(hash)
74
+ if(hash.include?(:name))
75
+ node = NodeDB.find_by_name(hash[:name])
76
+ hash.delete(:name)
77
+ if(node.kind_of?(Array))
78
+ node.each do |item|
79
+ item.update(hash)
80
+ end
81
+ elsif(!node.nil?)
82
+ node.update(hash)
83
+ end
84
+ elsif
85
+ hash.each do | key, value |
86
+ next if( key == :type or key ==:name) # cannot change name and type
87
+ self.send( key.to_s+"=", value)
67
88
  end
68
89
  end
69
90
  end
70
91
 
71
- def pre_draw
72
- GL.PushMatrix()
73
- GL.Translate(pre_translate.x, pre_translate.y, pre_translate.z) if(@pre_translate)
74
- GL.MultMatrix(@rotate.to_array) if(@rotate)
75
- GL.Translate(post_translate.x, post_translate.y, post_translate.z) if(@post_translate)
76
- end
92
+ def delete(node_name)
93
+ Util3D::check_arg_type(Symbol, node_name)
94
+ node = NodeDB.find_by_name(node_name)
77
95
 
78
- def post_draw
79
- GL.PopMatrix()
96
+ if(node.kind_of?(Array))
97
+ node.each do | node_ele |
98
+ remove_from_parents(node_ele)
99
+ end
100
+ elsif(!node.nil?)
101
+ remove_from_parents(node)
102
+ end
103
+ NodeDB.delete_by_name(node_name)
80
104
  end
81
105
 
82
- def ancestors
83
- rtn_ancestors_ary = []
84
- return ancestors_inner(rtn_ancestors_ary)
106
+ def remove_from_parents(node)
107
+ Util3D::check_arg_type(Node, node)
108
+ node.parents.each do |parent|
109
+ parent.remove_child_by_node(node)
110
+ end
85
111
  end
86
112
 
87
- protected
88
113
  def box_transform(box)
89
114
  box = box.translate(@pre_translate) if(@pre_translate)
90
115
  box = box.rotate(@rotate) if(@rotate)
@@ -92,24 +117,6 @@ protected
92
117
  return box
93
118
  end
94
119
 
95
- def create(hash)
96
- Util3D.check_key_arg(hash, :type)
97
- geom = hash[:geom]
98
- name = hash[:name]
99
- clazz = eval "Node" + hash[:type].to_s
100
- # node leaf constractor need 2 args
101
- if( clazz < NodeLeaf )
102
- new_node = clazz.new(geom, name)
103
- else
104
- new_node = clazz.new(name)
105
- end
106
- hash.each do | key, value |
107
- next if( key == :geom or key == :type or key ==:name)
108
- new_node.send( key.to_s+"=", value)
109
- end
110
- return new_node
111
- end
112
-
113
120
  def ancestors_inner(rtn_ancestors_ary)
114
121
  parents.each do |parent|
115
122
  if(!rtn_ancestors_ary.include?(parent.instance_id))
@@ -121,48 +128,36 @@ protected
121
128
  end
122
129
 
123
130
  private
124
- def remove(path_id)
125
- if(path_id.kind_of?(Integer))
126
- node = Node.find_node_by_path_id(path_id)
127
- else
128
- Util3D::raise_argurment_error(path_id)
129
- end
130
- node.parents.each do |parent|
131
- parent.remove_child_by_path_id(path_id)
132
- end
131
+ def gen_instance_id
132
+ return GL.GenLists(1)
133
133
  end
134
+ end
134
135
 
135
- def delete(node_name)
136
- if( node_name.kind_of?(Node) )
137
- node = node_name
138
- elsif(node_name.kind_of?(Symbol))
139
- node = Node.find_node_by_name(node_name)
136
+ class NodeDB
137
+ def self.add(node)
138
+ Util3D.check_arg_type(Node, node)
139
+ @node_db ||= Hash.new()
140
+ key = node.name
141
+ if(!@node_db.key?(key))
142
+ @node_db[key] = node
143
+ elsif(@node_db[key].kind_of?(Node))
144
+ @node_db[key] = [@node_db[key], node]
145
+ elsif(@node_db[key].kind_of?(Array))
146
+ @node_db[key].push(node)
140
147
  else
141
- Util3D::raise_argurment_error(node_name)
142
- end
143
- if(node.kind_of?(Array))
144
- node.each do | item |
145
- self.delete(item)
146
- end
147
- end
148
- if(!node.nil?)
149
- node.parents.each do |parent|
150
- parent.remove_child_by_node(node)
151
- end
152
- Node.delete_from_node_name_db_by_node(node)
148
+ raise
153
149
  end
154
150
  end
155
151
 
156
- def gen_instance_id
157
- id_adding = GL.GenLists(1)
158
- return id_adding
152
+ def self.find_by_name(node_name)
153
+ @node_db ||= Hash.new()
154
+ Util3D.check_arg_type(Symbol, node_name)
155
+ return @node_db[node_name]
159
156
  end
160
157
 
161
- @@path_id_list = Array.new()
162
- def gen_path_id
163
- id_adding = @@path_id_list.size
164
- @@path_id_list.push(id_adding)
165
- return id_adding
158
+ def self.delete_by_name(node_name)
159
+ return if @node_db.nil? || node_name.nil?
160
+ @node_db[node_name] = nil
166
161
  end
167
162
  end
168
163
  end
@@ -2,7 +2,7 @@ require 'disp3D'
2
2
 
3
3
  module Disp3D
4
4
  class NodeArrows < NodeLeaf
5
- attr_accessor :width
5
+ attr_for_disp :width
6
6
 
7
7
  def initialize(geom, name = nil)
8
8
  Util3D.check_arg_type(Symbol, name, true)
@@ -1,4 +1,3 @@
1
-
2
1
  require 'disp3D'
3
2
 
4
3
  module Disp3D
@@ -21,14 +20,14 @@ module Disp3D
21
20
  end
22
21
  end
23
22
 
24
- def draw
23
+ def draw currnet_view
25
24
  pre_draw()
26
25
  @children.each do |key, node|
27
26
  if(node.kind_of?(NodeLeaf))
28
- Node.add_to_path_db(key, node)
27
+ NodePathDB.add(key, node)
29
28
  GL.LoadName(key)
30
29
  end
31
- node.draw
30
+ node.draw currnet_view
32
31
  end
33
32
  post_draw()
34
33
  end
@@ -55,6 +54,14 @@ module Disp3D
55
54
  return @children[path_id]
56
55
  end
57
56
 
57
+ def child_nodes
58
+ return @children.values
59
+ end
60
+
61
+ def child_path_id
62
+ return @children.keys
63
+ end
64
+
58
65
  protected
59
66
  def remove_child_by_path_id(path_id)
60
67
  @children.delete(path_id)
@@ -64,25 +71,37 @@ protected
64
71
  @children.reject!{|key, value| value == child_node}
65
72
  end
66
73
 
74
+ def update_for_display
75
+ @children.each do |key, node|
76
+ node.update_for_display
77
+ end
78
+ end
67
79
  private
68
80
  def add_new(node_info, &block)
69
81
  if(block_given?)
70
82
  create_and_add_node_by_block(node_info, &block)
71
83
  elsif(node_info.kind_of?(Hash))
72
84
  create_and_add_node(node_info)
85
+ else
86
+ Util3D.raise_argurment_error(node_info)
73
87
  end
74
88
  end
75
89
 
76
- def create_and_add_node(hash)
77
- new_node = create(hash)
78
- add_node(new_node)
90
+ def remove(path_id)
91
+ if(path_id.kind_of?(Integer))
92
+ node = NodePathDB.find_by_path_id(path_id)
93
+ else
94
+ Util3D::raise_argurment_error(path_id)
95
+ end
96
+ node.parents.each do |parent|
97
+ parent.remove_child_by_path_id(path_id)
98
+ end
79
99
  end
80
100
 
81
- def create_and_add_node_by_block(hash, &block)
82
- hash[:type] = :Collection
83
- new_node = create(hash)
84
- new_node.instance_eval(&block) if(block_given?)
85
- add_node(new_node)
101
+ def add_node_by_name(node_name)
102
+ Util3D.check_arg_type(Symbol, node_name)
103
+ nodes = NodeDB.find_by_name(node_name)
104
+ add_node(nodes)
86
105
  end
87
106
 
88
107
  def add_node(node)
@@ -102,15 +121,42 @@ private
102
121
  node.parents.push(self)
103
122
  return new_id
104
123
  else
105
- raise # invalid Argument
124
+ Util3D.raise_argurment_error(node)
106
125
  end
107
126
  end
108
127
 
109
- def add_node_by_name(node_name)
110
- Util3D.check_arg_type(Symbol, node_name)
111
- nodes = Node.find_node_by_name(node_name)
112
- add_node(nodes)
128
+ def create_and_add_node(hash)
129
+ new_node = create(hash)
130
+ add_node(new_node)
131
+ end
132
+
133
+ def create_and_add_node_by_block(hash, &block)
134
+ hash[:type] = :Collection
135
+ new_node = create(hash)
136
+ new_node.instance_eval(&block) if(block_given?)
137
+ add_node(new_node)
113
138
  end
114
139
 
140
+ @@path_id_list = Array.new()
141
+ def gen_path_id
142
+ id_adding = @@path_id_list.size
143
+ @@path_id_list.push(id_adding)
144
+ return id_adding
145
+ end
146
+ end
147
+
148
+ # hold path id and node connectivity
149
+ class NodePathDB
150
+ def self.init
151
+ @path_db = Hash.new
152
+ end
153
+
154
+ def self.add(path_id, node)
155
+ return @path_db[path_id] = node
156
+ end
157
+
158
+ def self.find_by_path_id(path_id)
159
+ return @path_db[path_id]
160
+ end
115
161
  end
116
162
  end