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