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.
- data/README.rdoc +73 -1
- data/VERSION +1 -1
- data/disp3D.gemspec +97 -0
- data/example/stl_viewer/app_model.rb +8 -0
- data/example/stl_viewer/document.rb +15 -0
- data/example/stl_viewer/document_ctrl.rb +62 -0
- data/example/stl_viewer/gl_ctrl.rb +15 -0
- data/example/stl_viewer/main.rb +120 -0
- data/example/stl_viewer/mesh_info.rb +12 -0
- data/example/stl_viewer/stl_viewer.rb +9 -0
- data/lib/camera.rb +49 -35
- data/lib/disp3D.rb +19 -3
- data/lib/dsl.rb +18 -0
- data/lib/gl_view.rb +80 -0
- data/lib/glut_window.rb +60 -0
- data/lib/light.rb +49 -0
- data/lib/manipulator.rb +92 -21
- data/lib/node.rb +15 -9
- data/lib/node_arrows.rb +68 -0
- data/lib/node_collection.rb +14 -3
- data/lib/node_leaf.rb +80 -0
- data/lib/node_lines.rb +4 -7
- data/lib/node_points.rb +9 -11
- data/lib/node_polylines.rb +34 -0
- data/lib/node_tea_pod.rb +9 -2
- data/lib/node_text.rb +17 -0
- data/lib/node_tris.rb +24 -0
- data/lib/picked_result.rb +15 -0
- data/lib/picker.rb +56 -0
- data/lib/qt_widget_gl.rb +80 -0
- data/lib/scene_graph.rb +5 -0
- data/lib/stl.rb +92 -0
- data/lib/util.rb +18 -0
- data/test/test_data/binary_test.stl +0 -0
- data/test/test_data/cube-ascii.stl +86 -0
- data/test/test_dsl.rb +8 -0
- data/test/test_glut_window.rb +113 -0
- data/test/test_qtgl.rb +26 -0
- data/test/test_stl.rb +12 -0
- data/test/test_tea_pod.rb +13 -2
- metadata +41 -19
- data/lib/helloworld.rb +0 -112
- data/lib/view.rb +0 -47
- data/test/test_line.rb +0 -8
- data/test/test_lines.rb +0 -17
- data/test/test_point.rb +0 -25
- 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 '
|
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 '
|
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
|
data/lib/glut_window.rb
ADDED
@@ -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
|
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
|
-
|
10
|
-
|
11
|
-
@
|
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 @
|
17
|
-
|
18
|
-
|
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.
|
21
|
-
@camera.
|
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
|
-
|
24
|
-
|
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
|
-
|
27
|
-
@start_y = y
|
28
|
-
GLUT.PostRedisplay()
|
84
|
+
return z
|
29
85
|
end
|
30
86
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
7
|
+
@@named_nodes = nil
|
8
|
+
def initialize(geometry)
|
9
|
+
@translate = nil
|
10
|
+
end
|
10
11
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
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
|
24
|
-
|
25
|
-
|
29
|
+
def box
|
30
|
+
# should be implimented in child class
|
31
|
+
raise
|
26
32
|
end
|
27
33
|
end
|
28
34
|
end
|
data/lib/node_arrows.rb
ADDED
@@ -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
|