disp3D 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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