disp3D 0.1.0 → 0.1.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 (47) hide show
  1. data/README.rdoc +73 -1
  2. data/VERSION +1 -1
  3. data/disp3D.gemspec +97 -0
  4. data/example/stl_viewer/app_model.rb +8 -0
  5. data/example/stl_viewer/document.rb +15 -0
  6. data/example/stl_viewer/document_ctrl.rb +62 -0
  7. data/example/stl_viewer/gl_ctrl.rb +15 -0
  8. data/example/stl_viewer/main.rb +120 -0
  9. data/example/stl_viewer/mesh_info.rb +12 -0
  10. data/example/stl_viewer/stl_viewer.rb +9 -0
  11. data/lib/camera.rb +49 -35
  12. data/lib/disp3D.rb +19 -3
  13. data/lib/dsl.rb +18 -0
  14. data/lib/gl_view.rb +80 -0
  15. data/lib/glut_window.rb +60 -0
  16. data/lib/light.rb +49 -0
  17. data/lib/manipulator.rb +92 -21
  18. data/lib/node.rb +15 -9
  19. data/lib/node_arrows.rb +68 -0
  20. data/lib/node_collection.rb +14 -3
  21. data/lib/node_leaf.rb +80 -0
  22. data/lib/node_lines.rb +4 -7
  23. data/lib/node_points.rb +9 -11
  24. data/lib/node_polylines.rb +34 -0
  25. data/lib/node_tea_pod.rb +9 -2
  26. data/lib/node_text.rb +17 -0
  27. data/lib/node_tris.rb +24 -0
  28. data/lib/picked_result.rb +15 -0
  29. data/lib/picker.rb +56 -0
  30. data/lib/qt_widget_gl.rb +80 -0
  31. data/lib/scene_graph.rb +5 -0
  32. data/lib/stl.rb +92 -0
  33. data/lib/util.rb +18 -0
  34. data/test/test_data/binary_test.stl +0 -0
  35. data/test/test_data/cube-ascii.stl +86 -0
  36. data/test/test_dsl.rb +8 -0
  37. data/test/test_glut_window.rb +113 -0
  38. data/test/test_qtgl.rb +26 -0
  39. data/test/test_stl.rb +12 -0
  40. data/test/test_tea_pod.rb +13 -2
  41. metadata +41 -19
  42. data/lib/helloworld.rb +0 -112
  43. data/lib/view.rb +0 -47
  44. data/test/test_line.rb +0 -8
  45. data/test/test_lines.rb +0 -17
  46. data/test/test_point.rb +0 -25
  47. data/test/test_points.rb +0 -27
data/lib/disp3D.rb CHANGED
@@ -5,14 +5,30 @@ require 'gmath3D'
5
5
  require 'opengl'
6
6
  require 'glut'
7
7
 
8
- require 'view'
8
+ require 'util'
9
+ require 'dsl'
10
+ require 'stl'
11
+
12
+ require 'gl_view'
13
+
14
+ require 'glut_window'
15
+
9
16
  require 'camera'
17
+ require 'light'
10
18
  require 'manipulator'
19
+ require 'picker'
20
+ require 'picked_result'
11
21
  require 'scene_graph'
22
+
12
23
  require 'node'
13
24
  require 'node_collection'
25
+ require 'node_leaf'
14
26
 
15
27
  require 'node_tea_pod'
16
- require 'node_lines'
17
- require 'node_points'
28
+ require 'node_text'
18
29
 
30
+ require 'node_points'
31
+ require 'node_lines'
32
+ require 'node_polylines'
33
+ require 'node_tris'
34
+ require 'node_arrows'
data/lib/dsl.rb ADDED
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'disp3D'
3
+
4
+ module Disp3D
5
+ # SDLは3次元ビューに対して操作を行うための、ミニ言語である。
6
+ # 基本的にユーザーはこのインターフェースによって、3次元ビューに対して操作する
7
+ class GLView
8
+ # 表示要素に対する操作
9
+ # (例)
10
+ # 括弧内は入れても入れなくてもよい
11
+ # Create Point named point1 [0,0,0]
12
+ # Create Points named points [[0,0,1], [1,0,1], [1,2,1]]
13
+ # Create Line named line1 from[0,0,0] to[1,2,0]
14
+ # Create Plane named plane1 base[0,0,0] normal[0,0,1]
15
+ # Create Polyline named polyline1 (vertices) [[1,2,1], [1,4,3], [1,2,4]]
16
+ # →これによって、geometryの要素を作成する
17
+ end
18
+ end
data/lib/gl_view.rb ADDED
@@ -0,0 +1,80 @@
1
+ require 'disp3D'
2
+
3
+ module Disp3D
4
+ # GLView class hold primary object for 3D displaying like camera, scene_graph.
5
+ # User never use this class
6
+ # Use QtWidgetGL class (in Qt Application)
7
+ # Use GLWindow class (in GLUT Window)
8
+ class GLView
9
+ attr_reader :world_scene_graph
10
+ attr_reader :camera
11
+ attr_reader :manipulator
12
+ attr_reader :light
13
+ attr_reader :picker
14
+
15
+ attr_reader :mouse_move_proc
16
+ attr_reader :mouse_press_proc
17
+ attr_reader :mouse_release_proc
18
+
19
+ attr_accessor :bk_color
20
+
21
+ def initialize(width, height)
22
+ GL.Enable(GL::GL_DEPTH_TEST)
23
+
24
+ GL.FrontFace(GL::GL_CW)
25
+
26
+ GL.Enable(GL::GL_AUTO_NORMAL)
27
+ GL.Enable(GL::GL_NORMALIZE)
28
+
29
+ GL.Enable(GL::GL_DEPTH_TEST)
30
+ GL.DepthFunc(GL::GL_LESS)
31
+
32
+ GL.Enable(GL::BLEND)
33
+ GL.BlendFunc(GL::GL_SRC_ALPHA, GL::GL_ONE_MINUS_SRC_ALPHA)
34
+
35
+ @light = Light.new()
36
+ @camera = Camera.new()
37
+ @manipulator = Manipulator.new(@camera, width, height)
38
+ @world_scene_graph = SceneGraph.new()
39
+ @picker = Picker.new(self)
40
+ @bk_color = [0.28,0.23,0.55,1]
41
+
42
+ @mouse_move_proc = nil
43
+ end
44
+
45
+ def display()
46
+ GL.ClearColor(@bk_color[0],@bk_color[1],@bk_color[2],@bk_color[3])
47
+ GL.Clear(GL::GL_COLOR_BUFFER_BIT | GL::GL_DEPTH_BUFFER_BIT)
48
+
49
+ @light.display() if(@light)
50
+
51
+ @camera.display() if(@camera)
52
+ @world_scene_graph.display() if(@world_scene_graph)
53
+ end
54
+
55
+ def centering
56
+ center_pos = @world_scene_graph.bounding_box.center * -1 # TODO refactaring vector3.rb
57
+ @manipulator.centering(center_pos)
58
+ end
59
+
60
+ def fit
61
+ centering
62
+ length = @world_scene_graph.bounding_box.length # TODO refactaring box.rb
63
+ orth_length = Math.sqrt( length[0]*length[0] + length[1]*length[1] + length[2]*length[2] )
64
+ @manipulator.fit(orth_length/2.0)
65
+ end
66
+
67
+ def set_mouse_move(proc)
68
+ @mouse_move_proc = proc
69
+ end
70
+
71
+ def set_mouse_press(proc)
72
+ @mouse_press_proc = proc
73
+ end
74
+
75
+ def set_mouse_release(proc)
76
+ @mouse_release_proc = proc
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,60 @@
1
+ require 'disp3D'
2
+
3
+ module Disp3D
4
+ class GLUTWindow < GLView
5
+ def initialize(width, height)
6
+ x = 100
7
+ y = 100
8
+ GLUT.InitWindowPosition(x, y)
9
+ GLUT.InitWindowSize(width, height)
10
+ GLUT.Init
11
+ GLUT.InitDisplayMode(GLUT::GLUT_DOUBLE | GLUT::GLUT_RGB | GLUT::GLUT_DEPTH)
12
+ GLUT.CreateWindow("Disp3D view test")
13
+ GLUT.DisplayFunc(method(:display).to_proc())
14
+ GLUT.ReshapeFunc(method(:reshape).to_proc())
15
+
16
+ GLUT.MouseFunc(method(:mouse).to_proc())
17
+ GLUT.MotionFunc(method(:motion).to_proc())
18
+ GLUT.PassiveMotionFunc(method(:passive_motion).to_proc())
19
+
20
+ super(width, height)
21
+ end
22
+
23
+ def display
24
+ super
25
+ GLUT.SwapBuffers()
26
+ end
27
+
28
+ def reshape(w,h)
29
+ @camera.reshape(w,h)
30
+ end
31
+
32
+ def mouse(button,state,x,y)
33
+ if(state == GLUT::GLUT_UP)
34
+ @mouse_release_proc.call(self, button, x, y) if( @mouse_release_proc != nil)
35
+ elsif(state == GLUT::GLUT_DOWN)
36
+ @mouse_press_proc.call(self, button, x, y) if( @mouse_press_proc != nil)
37
+ end
38
+ @manipulator.mouse(button,state,x,y)
39
+ end
40
+
41
+ def motion(x,y)
42
+ @mouse_move_proc.call(self, x,y) if( @mouse_move_proc != nil)
43
+
44
+ update = @manipulator.motion(x,y)
45
+ if(update)
46
+ GLUT.PostRedisplay()
47
+ end
48
+ end
49
+
50
+ def passive_motion(x,y)
51
+ @mouse_move_proc.call(self, x,y) if( @mouse_move_proc != nil)
52
+ end
53
+
54
+ def start
55
+ fit
56
+ GLUT.MainLoop()
57
+ end
58
+
59
+ end
60
+ end
data/lib/light.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'disp3D'
2
+
3
+ module Disp3D
4
+ class Light
5
+ LIGHT_POSITION_1 = [0.25, 1.0, 0.25]
6
+
7
+ def display()
8
+ idx = 0
9
+ GL.Enable(GL::GL_LIGHTING)
10
+ all_disable = true
11
+ @enable.each do | enable |
12
+ if(enable)
13
+ GL.Enable( @light_id[idx])
14
+ GL.Lightfv( @light_id[idx], GL::GL_POSITION, @position[idx] )
15
+ GL.Lightfv( @light_id[idx], GL::GL_DIFFUSE, @deffuse[idx] )
16
+ GL.Lightfv( @light_id[idx], GL::GL_AMBIENT, @ambient[idx] )
17
+ GL.Lightfv( @light_id[idx], GL::GL_SPECULAR, @specular[idx] )
18
+ all_disable = false
19
+ end
20
+ end
21
+ GL.Enable(GL::GL_LIGHT0) if(all_disable)
22
+ end
23
+
24
+ def initialize()
25
+ @diffuse_default = [0.7, 0.7, 0.7, 1]
26
+ @ambient_default = [0.2, 0.2, 0.2, 1]
27
+ @specular_default = [1, 1, 1, 1]
28
+ @position_default = [0.25, 1.0, 0.25]
29
+
30
+ light_count = 8 # openGL spec
31
+
32
+ @enable = [true, false, false, false, false, false, false, false]
33
+ @deffuse = Array.new(light_count, @diffuse_default)
34
+ @ambient = Array.new(light_count, @ambient_default)
35
+ @specular = Array.new(light_count, @specular_default)
36
+ @position = Array.new(light_count, @position_default)
37
+ @light_id = Array.new(light_count)
38
+ @light_id[0] = GL::GL_LIGHT0
39
+ @light_id[1] = GL::GL_LIGHT1
40
+ @light_id[2] = GL::GL_LIGHT2
41
+ @light_id[3] = GL::GL_LIGHT3
42
+ @light_id[4] = GL::GL_LIGHT4
43
+ @light_id[5] = GL::GL_LIGHT5
44
+ @light_id[6] = GL::GL_LIGHT6
45
+ @light_id[7] = GL::GL_LIGHT7
46
+ end
47
+
48
+ end
49
+ end
data/lib/manipulator.rb CHANGED
@@ -1,41 +1,112 @@
1
1
  require 'disp3D'
2
2
 
3
+ include GMath3D
3
4
  module Disp3D
4
5
  class Manipulator
6
+ def initialize(camera, w, h)
7
+ @camera = camera
8
+ @start_x = 0
9
+ @start_y = 0
10
+ reset_size(w, h)
11
+
12
+ @moving = false
13
+ @scalling = false
14
+ @translating = false
15
+ @trackball_size = 0.8
16
+ end
17
+
18
+ def reset_size(width, height)
19
+ @width = width
20
+ @height = height
21
+ end
22
+
5
23
  def mouse(button,state,x,y)
6
- if button == GLUT::GLUT_LEFT_BUTTON && state == GLUT::GLUT_DOWN then
24
+ if (state == GLUT::GLUT_DOWN &&
25
+ ((button == GLUT::GLUT_RIGHT_BUTTON && @moving == true) ||
26
+ (button == GLUT::GLUT_LEFT_BUTTON && @scalling == true) ))
27
+ # pushed left and right at the same time
28
+ @translating = true
29
+ @start_x = x
30
+ @start_y = y
31
+ elsif (button == GLUT::GLUT_RIGHT_BUTTON && state == GLUT::GLUT_DOWN)
32
+ @scalling = true
33
+ @start_y = y
34
+ elsif ( button == GLUT::GLUT_LEFT_BUTTON && state == GLUT::GLUT_DOWN )
35
+ @moving = true
7
36
  @start_x = x
8
37
  @start_y = y
9
- @drag_flg = true
10
- elsif state == GLUT::GLUT_UP then
11
- @drag_flg = false
38
+ elsif ( button == GLUT::GLUT_RIGHT_BUTTON && state == GLUT::GLUT_UP )
39
+ @scalling = false
40
+ @translating = false
41
+ elsif ( button == GLUT::GLUT_LEFT_BUTTON && state == GLUT::GLUT_UP )
42
+ @moving = false
43
+ @translating = false
12
44
  end
13
45
  end
14
46
 
47
+ # return true if should be redisplay
15
48
  def motion(x,y)
16
- if @drag_flg then
17
- dx = x - @start_x
18
- dy = y - @start_y
49
+ if( @translating )
50
+ delta_x = 2*((@start_x - x).to_f/@width)
51
+ delta_y = 2*((@start_y - y).to_f/@height)
52
+ @start_x = x
53
+ @start_y = y
19
54
 
20
- @camera.rotY += dx
21
- @camera.rotY = @camera.rotY % 360
55
+ @camera.translate.x -= delta_x
56
+ @camera.translate.y += delta_y
57
+ return true
58
+ elsif ( @scalling )
59
+ @camera.scale *= (1.0+(@start_y - y).to_f/@height)
60
+ @start_y = y
61
+ return true
62
+ elsif ( @moving )
63
+ @lastquat =trackball(
64
+ (2.0 * @start_x - @width) / @width,
65
+ (@height - 2.0 * @start_y) / @height,
66
+ (2.0 * x - @width) / @width,
67
+ (@height - 2.0 * y) / @height)
68
+ @start_x = x
69
+ @start_y = y
70
+ @camera.rotation = @lastquat * @camera.rotation if( @lastquat )
71
+ return true
72
+ end
73
+ return false
74
+ end
22
75
 
23
- @camera.rotX += dy
24
- @camera.rotX = @camera.rotX % 360
76
+ def project_to_sphere(r, x, y)
77
+ d = Math.sqrt(x*x + y*y)
78
+ if (d < r * Math.sqrt(2)/2) # inside sphere
79
+ z = Math.sqrt(r*r - d*d)
80
+ else
81
+ t = r / Math.sqrt(2)
82
+ z = t*t / d
25
83
  end
26
- @start_x = x
27
- @start_y = y
28
- GLUT.PostRedisplay()
84
+ return z
29
85
  end
30
86
 
31
- def initialize(camera)
32
- @camera = camera
33
- @start_x = 0
34
- @start_y = 0
35
- @drag_flg = false
87
+ def trackball(p1x, p1y, p2x, p2y)
88
+ if( p1x == p2x && p1y == p2y)
89
+ return Quat.new(0,0,0,1)
90
+ end
91
+ p1 = Vector3.new( p1x, p1y, project_to_sphere(@trackball_size, p1x, p1y))
92
+ p2 = Vector3.new( p2x, p2y, project_to_sphere(@trackball_size, p2x, p2y))
93
+ a = p1.cross(p2)
94
+ d = p1 - p2
95
+ t = d.length / (2*@trackball_size)
96
+ t = 1 if( t > 1)
97
+ t = -1 if( t < -1 )
98
+ phi = 2*Math.asin(t)
99
+ a = a.normalize
100
+ return Quat.from_axis(a, phi)
101
+ end
102
+
103
+ def centering(center_pos)
104
+ return if center_pos == nil
105
+ @camera.translate = center_pos
106
+ end
36
107
 
37
- GLUT.MouseFunc(method(:mouse).to_proc())
38
- GLUT.MotionFunc(method(:motion).to_proc())
108
+ def fit(radius)
109
+ @camera.fit(radius, @width, @height)
39
110
  end
40
111
  end
41
112
  end
data/lib/node.rb CHANGED
@@ -2,16 +2,22 @@ require 'disp3D'
2
2
 
3
3
  module Disp3D
4
4
  class Node
5
- attr_accessor :geom
6
-
7
5
  attr_accessor :translate
8
6
 
9
- attr_accessor :color
7
+ @@named_nodes = nil
8
+ def initialize(geometry)
9
+ @translate = nil
10
+ end
10
11
 
11
- def pre_draw
12
- GL.Color(@color[0], @color[1], @color[2]) if(@color && @color.size == 3)
13
- GL.Color(@color[0], @color[1], @color[2], @color[3]) if(@color && @color.size == 4)
12
+ def self.init_node_list
13
+ @@named_nodes = Hash.new
14
+ end
14
15
 
16
+ def self.from_id(id)
17
+ return @@named_nodes[id]
18
+ end
19
+
20
+ def pre_draw
15
21
  GL.PushMatrix()
16
22
  GL.Translate(translate[0], translate[1], translate[2]) if(@translate)
17
23
  end
@@ -20,9 +26,9 @@ module Disp3D
20
26
  GL.PopMatrix()
21
27
  end
22
28
 
23
- def initialize(geometry)
24
- @geom = geometry
25
- @color = [1.0, 1.0, 1.0]
29
+ def box
30
+ # should be implimented in child class
31
+ raise
26
32
  end
27
33
  end
28
34
  end
@@ -0,0 +1,68 @@
1
+ require 'disp3D'
2
+
3
+ module Disp3D
4
+ class NodeArrows < NodeLeaf
5
+ attr_accessor :width
6
+
7
+ protected
8
+ def draw_element
9
+ if(@geom)
10
+ GL.ShadeModel(GL::FLAT)
11
+ GL.LineWidth(@width) if(@width)
12
+ GL.Begin(GL::LINES)
13
+ if(@geom.kind_of?(GMath3D::FiniteLine))
14
+ draw_element_inner(@geom)
15
+ elsif(@geom.kind_of?(Array))
16
+ @geom.each do |line|
17
+ draw_element_inner(line)
18
+ end
19
+ end
20
+ GL.End()
21
+ end
22
+ end
23
+
24
+ def draw_element_inner(line)
25
+ start_point = line.start_point
26
+ end_point = line.end_point
27
+
28
+ GL.Vertex( start_point.x, start_point.y, start_point.z )
29
+ GL.Vertex( end_point.x, end_point.y, end_point.z )
30
+
31
+ # draw arrow head!
32
+ head_angle = 15.0 ;
33
+ head_ratio = 0.2 ;
34
+
35
+ vector = line.direction
36
+ orh = vector.arbitrary_orthogonal
37
+ orh2 = vector.cross(orh)
38
+ orh2 = orh2.normalize
39
+
40
+ body_length = vector.length
41
+ orh_length = body_length*Math.tan(head_angle*Math::PI/180.0)
42
+
43
+ head_vec1 = Vector3.new( -vector.x + orh.x*orh_length, -vector.y + orh.y*orh_length, -vector.z + orh.z*orh_length )
44
+ head_vec2 = Vector3.new( -vector.x + orh2.x*orh_length, -vector.y + orh2.y*orh_length, -vector.z + orh2.z*orh_length )
45
+ head_vec3 = Vector3.new( -vector.x - orh.x*orh_length, -vector.y - orh.y*orh_length, -vector.z - orh.z*orh_length )
46
+ head_vec4 = Vector3.new( -vector.x - orh2.x*orh_length, -vector.y - orh2.y*orh_length, -vector.z - orh2.z*orh_length )
47
+
48
+ head_bases = Array.new(4)
49
+ head_bases[0] = Vector3.new( end_point.x + head_vec1.x*head_ratio, end_point.y + head_vec1.y*head_ratio, end_point.z + head_vec1.z*head_ratio )
50
+ head_bases[1] = Vector3.new( end_point.x + head_vec2.x*head_ratio, end_point.y + head_vec2.y*head_ratio, end_point.z + head_vec2.z*head_ratio )
51
+ head_bases[2] = Vector3.new( end_point.x + head_vec3.x*head_ratio, end_point.y + head_vec3.y*head_ratio, end_point.z + head_vec3.z*head_ratio )
52
+ head_bases[3] = Vector3.new( end_point.x + head_vec4.x*head_ratio, end_point.y + head_vec4.y*head_ratio, end_point.z + head_vec4.z*head_ratio )
53
+
54
+ head_bases.each do | head_base |
55
+ GL.Vertex( head_base.x, head_base.y, head_base.z )
56
+ GL.Vertex( end_point.x, end_point.y, end_point.z )
57
+ end
58
+
59
+ arrow_size_minus = head_bases.size - 1
60
+ arrow_size_minus.times do |i|
61
+ GL.Vertex( head_bases[i ].x, head_bases[i ].y, head_bases[i ].z )
62
+ GL.Vertex( head_bases[i+1].x, head_bases[i+1].y, head_bases[i+1].z )
63
+ end
64
+ GL.Vertex( head_bases[arrow_size_minus].x, head_bases[arrow_size_minus].y, head_bases[arrow_size_minus].z )
65
+ GL.Vertex( head_bases[0].x, head_bases[0].y, head_bases[0].z )
66
+ end
67
+ end
68
+ end