teien 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in teien.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 abexsoft@gmail.com
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Teien
2
+
3
+ Teien will be a platform to make 3D world easily with Ruby.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'teien'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install ruby-ogre
18
+ $ gem install ruby-bullet
19
+ $ gem install teienlib
20
+ $ gem install pkg/teien-<version>.gem
21
+
22
+ ## Usage
23
+
24
+ Run a sample application.
25
+
26
+ $ /var/lib/gems/1.9.1/gems/teien-<version>/sample/standalone/hello_garden/run
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/teien ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This script is a environment setting helper on the startup.
4
+ # 1. set a LD_LIBRARY_PATH(or PATH) value for dynamic libraries.
5
+ # 2. restart with above value.
6
+ # 3. set a LOAD_PATH value for ruby libraries.
7
+
8
+ if (ARGV[0] == "-h" || ARGV[0] == "--help")
9
+ puts "Usage: teien file"
10
+ exit
11
+ end
12
+
13
+ #
14
+ # require this file directly at first line, unless you set
15
+ # RUBYLIB and LD_LIBRARY_PATH. (check sample code)
16
+ #
17
+ require 'rbconfig'
18
+ require 'OgreConfig'
19
+
20
+ $topDir = File.dirname(File.dirname(File.expand_path(__FILE__)))
21
+ libPath = $topDir + "/lib"
22
+ extPath = OgreConfig::getDepsLibPath
23
+
24
+ # needed by dynamic library.
25
+ if (/mingw/ =~ RUBY_PLATFORM)
26
+ ldLibPath = extPath + ";" + OgreConfig::getLib + ";" + libPath
27
+ if (ENV["PATH"] == nil)
28
+ ENV["PATH"] = ldLibPath
29
+ exec("ruby #{$0} #{ARGV.join(" ")}")
30
+ elsif (!ENV["PATH"].include?(ldLibPath))
31
+ ENV["PATH"] = ldLibPath + ";" +ENV["PATH"]
32
+ exec("ruby #{$0} #{ARGV.join(" ")}")
33
+ end
34
+ else
35
+ ldLibPath = extPath + ":" + libPath
36
+ if (ENV["LD_LIBRARY_PATH"] == nil)
37
+ ENV["LD_LIBRARY_PATH"] = ldLibPath
38
+ exec($0, *ARGV)
39
+ elsif(!ENV["LD_LIBRARY_PATH"].include?(ldLibPath))
40
+ ENV["LD_LIBRARY_PATH"] = ldLibPath + ":" + ENV["LD_LIBRARY_PATH"]
41
+ exec($0, *ARGV)
42
+ end
43
+ end
44
+
45
+ $LOAD_PATH.push(libPath)
46
+ $LOAD_PATH.push("./")
47
+
48
+ load ARGV[0]
49
+
@@ -0,0 +1,142 @@
1
+ class AnimationOperator
2
+ BL_MODE_SWITCH = 0 # stop current animation and start next animation.
3
+ BL_MODE_CONCURRENT = 1 # cross fade, blend current animation out while blending next animation in.
4
+ BL_MODE_FIRSTFRAME = 2 # blend current animation to first frame of next animation, when done, start next animation.
5
+
6
+ def initialize(entity)
7
+ @entity = entity
8
+ @state = nil
9
+ @nextState = nil
10
+ @mode = BL_MODE_CONCURRENT
11
+ @duration = 0.2
12
+ @timeLeft = 0
13
+ @complete = false
14
+ @loop = false
15
+
16
+ # @blender = Ogrelet::AnimationBlender.new(entity)
17
+ end
18
+
19
+ def init(name, loop)
20
+ initializeAllAnimations()
21
+ play(name, loop)
22
+ end
23
+
24
+ def initializeAllAnimations()
25
+ set = @entity.getAllAnimationStates()
26
+ set.each_AnimationState {|state|
27
+ state.setEnabled(false)
28
+ state.setWeight(0)
29
+ state.setTimePosition(0)
30
+ }
31
+ end
32
+
33
+ def setEnabled(bl)
34
+ # @blender.getSource().setEnabled(bl)
35
+ end
36
+
37
+ def setBlendingMode(mode)
38
+ @mode = mode
39
+ end
40
+
41
+ def setBlengingDuration(duration)
42
+ @duration = duration
43
+ end
44
+
45
+ def play(name, loop)
46
+ @loop = loop
47
+
48
+ unless @state
49
+ @state = @entity.getAnimationState(name)
50
+ @state.setEnabled(true)
51
+ @state.setWeight(1)
52
+ @state.setTimePosition(0)
53
+ @state.setLoop(loop)
54
+ return
55
+ end
56
+
57
+ case @mode
58
+ when BL_MODE_SWITCH
59
+ @state.setEnabled(false)
60
+ @state = @entity.getAnimationState(name)
61
+ @state.setEnabled(true)
62
+ @state.setWeight(1)
63
+ @state.setTimePosition(0)
64
+ @timeLeft = 0
65
+ else
66
+ newState = @entity.getAnimationState(name)
67
+ if @timeLeft > 0
68
+ if newState.getAnimationName == @nextState.getAnimationName
69
+ return
70
+ elsif newState.getAnimationName == @state.getAnimationName
71
+ # going back to the source state
72
+ @state = @nextState
73
+ @nextState = newState
74
+ @timeLeft = @duration - @timeLeft
75
+ else
76
+ if @timeLeft < @duration * 0.5
77
+ # simply replace the target with this one
78
+ @nextState.setEnabled(false)
79
+ @nextState.setWeight(0)
80
+ else
81
+ # old target becomes new source
82
+ @state.setEnabled(false)
83
+ @state.setWeight(0)
84
+ @state = @nextState
85
+ end
86
+
87
+ @nextState = newState
88
+ @nextState.setEnabled(true)
89
+ @nextState.setWeight( 1.0 - @timeLeft / @duration )
90
+ @nextState.setTimePosition(0)
91
+ end
92
+ else
93
+ return if newState.getAnimationName == @state.getAnimationName
94
+
95
+ # assert( target == 0, "target should be 0 when not blending" )
96
+ # @state.setEnabled(true)
97
+ # @state.setWeight(1)
98
+ # mTransition = transition;
99
+ @timeLeft = @duration
100
+ @nextState = newState
101
+ @nextState.setEnabled(true)
102
+ @nextState.setWeight(0)
103
+ @nextState.setTimePosition(0)
104
+ end
105
+ end
106
+ # @blender.blend(name, Ogrelet::AnimationBlender::BlendWhileAnimating, 0.2, loop)
107
+ end
108
+
109
+ def addTime(delta)
110
+ if @state
111
+ if @timeLeft > 0
112
+ @timeLeft -= delta
113
+
114
+ if @timeLeft < 0
115
+ @state.setEnabled(false)
116
+ @state.setWeight(0)
117
+ @state = @nextState
118
+ @state.setEnabled(true)
119
+ @state.setWeight(1)
120
+ @nextState = nil
121
+ else
122
+ # still blending, advance weights
123
+ @state.setWeight(@timeLeft / @duration)
124
+ @nextState.setWeight(1.0 - @timeLeft / @duration)
125
+ if(@mode == BL_MODE_CONCURRENT)
126
+ @nextState.addTime(delta)
127
+ end
128
+ end
129
+ end
130
+
131
+ if @state.getTimePosition() >= @state.getLength()
132
+ @complete = true
133
+ else
134
+ @complete = false
135
+ end
136
+
137
+ @state.addTime(delta)
138
+ @state.setLoop(@loop)
139
+ end
140
+ # @blender.addTime(delta)
141
+ end
142
+ end
@@ -0,0 +1,25 @@
1
+ require 'teien/camera_mover'
2
+
3
+ module Teien
4
+
5
+ class Camera
6
+ def initialize(cam)
7
+ # Ogre::Camera
8
+ @camera = cam
9
+ @mover = CameraMover.new(cam)
10
+ end
11
+
12
+ def get_mover()
13
+ return @mover
14
+ end
15
+
16
+ def get_position
17
+ return Vector3D.to_self(@camera.getPosition())
18
+ end
19
+
20
+ def get_direction
21
+ return Vector3D.to_self(@camera.getDirection())
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,193 @@
1
+ module Teien
2
+
3
+ class CameraMover
4
+ CS_FREELOOK = 0
5
+ CS_ORBIT = 1
6
+ CS_MANUAL = 2
7
+ CS_TPS = 3
8
+
9
+ CAM_HEIGHT = 5.0
10
+
11
+ attr_accessor :height
12
+ attr_accessor :camera_pivot
13
+ attr_accessor :camera
14
+
15
+ def initialize(cam)
16
+ @camera = cam
17
+ @camera.setPosition(0, 0, 0)
18
+ @camera.setNearClipDistance(0.1)
19
+
20
+ @style = CS_FREELOOK
21
+
22
+ # CS_FREELOOK, CS_ORBIT, CS_MANUAL
23
+ @sdk_camera_man = OgreBites::SdkCameraMan.new(@camera)
24
+ @evt_frame = Ogre::FrameEvent.new
25
+
26
+ # CS_TPS
27
+ @height = CAM_HEIGHT
28
+ @camera_pivot = cam.getSceneManager().getRootSceneNode().createChildSceneNode()
29
+ @camera_goal = @camera_pivot.createChildSceneNode(Ogre::Vector3.new(0, 0, 5))
30
+
31
+ @camera_pivot.setFixedYawAxis(true)
32
+ @camera_goal.setFixedYawAxis(true)
33
+
34
+ @pivot_pitch = 0
35
+
36
+ end
37
+
38
+ def set_style(style)
39
+ @style = style
40
+ case @style
41
+ when CS_FREELOOK
42
+ @sdk_camera_man.setStyle(OgreBites::CS_FREELOOK)
43
+ when CS_ORBIT
44
+ @sdk_camera_man.setStyle(OgreBites::CS_ORBIT)
45
+ else # CS_MANUAL, CS_TPS
46
+ @sdk_camera_man.setStyle(OgreBites::CS_MANUAL)
47
+ end
48
+ end
49
+
50
+ def set_target(target)
51
+ @target = target
52
+ if @style == CS_TPS
53
+ @camera.setAutoTracking(false)
54
+ @camera.moveRelative(Ogre::Vector3.new(0, 0, 0))
55
+ update_camera(1.0)
56
+ else
57
+ @sdk_camera_man.setTarget(target.pivotSceneNode)
58
+ end
59
+ end
60
+
61
+ def set_position(pos)
62
+ @camera.setPosition(Vector3D.to_ogre(pos)) if @style == CS_FREELOOK
63
+ end
64
+
65
+ def look_at(pos)
66
+ @camera.lookAt(Vector3D.to_ogre(pos)) if @style == CS_FREELOOK
67
+ end
68
+
69
+ def set_yaw_pitch_dist(yaw, pitch, dist)
70
+ @sdk_camera_man.setYawPitchDist(yaw, pitch, dist) if @style == CS_ORBIT
71
+ end
72
+
73
+ def move_forward(bl)
74
+ evt = OIS::KeyEvent.new(nil, OIS::KC_W, 0)
75
+ if bl
76
+ @sdk_camera_man.injectKeyDown(evt)
77
+ else
78
+ @sdk_camera_man.injectKeyUp(evt)
79
+ end
80
+ end
81
+
82
+ def move_backward(bl)
83
+ evt = OIS::KeyEvent.new(nil, OIS::KC_S, 0)
84
+ if bl
85
+ @sdk_camera_man.injectKeyDown(evt)
86
+ else
87
+ @sdk_camera_man.injectKeyUp(evt)
88
+ end
89
+ end
90
+
91
+ def move_left(bl)
92
+ evt = OIS::KeyEvent.new(nil, OIS::KC_A, 0)
93
+ if bl
94
+ @sdk_camera_man.injectKeyDown(evt)
95
+ else
96
+ @sdk_camera_man.injectKeyUp(evt)
97
+ end
98
+ end
99
+
100
+ def move_right(bl)
101
+ evt = OIS::KeyEvent.new(nil, OIS::KC_D, 0)
102
+ if bl
103
+ @sdk_camera_man.injectKeyDown(evt)
104
+ else
105
+ @sdk_camera_man.injectKeyUp(evt)
106
+ end
107
+ end
108
+
109
+
110
+ def update(delta)
111
+ if (@style == CS_TPS)
112
+ update_camera(delta)
113
+ else
114
+ @evt_frame.timeSinceLastFrame = delta
115
+ @sdk_camera_man.frameRenderingQueued(@evt_frame)
116
+ end
117
+ end
118
+
119
+ #
120
+ # This method moves this camera position to the goal position smoothly.
121
+ # In general, should be called in the frameRenderingQueued handler.
122
+ #
123
+ def update_camera(deltaTime)
124
+ # place the camera pivot roughly at the character's shoulder
125
+ @camera_pivot.setPosition(Vector3D::to_ogre(@target.get_position()) + Ogre::Vector3.UNIT_Y * @height)
126
+ # move the camera smoothly to the goal
127
+ goalOffset = @camera_goal._getDerivedPosition() - @camera.getPosition()
128
+ @camera.move(goalOffset * deltaTime * 9.0)
129
+ # always look at the pivot
130
+ @camera.lookAt(@camera_pivot._getDerivedPosition())
131
+ end
132
+
133
+ def mouse_moved(evt)
134
+ if @style == CS_TPS
135
+
136
+ # deal with a warp.
137
+ if evt.state.X.rel.abs > 300
138
+ #puts "#{evt.state.X.rel}, #{evt.state.X.abs}"
139
+ return true
140
+ end
141
+
142
+ update_camera_goal(-0.05 * evt.state.X.rel,
143
+ -0.05 * evt.state.Y.rel,
144
+ -0.0005 * evt.state.Z.rel)
145
+ else
146
+ @sdk_camera_man.injectMouseMove(evt)
147
+ end
148
+ return true
149
+ end
150
+
151
+ #
152
+ # This method updates the goal position, which this camera should be placed finally.
153
+ # In general, should be called when the mouse is moved.
154
+ # *deltaYaw*::_float_, degree value.
155
+ # *deltaPitch*::_float_, degree value.
156
+ # *deltaZoom*::_float_, zoom
157
+ #
158
+ def update_camera_goal(deltaYaw, deltaPitch, deltaZoom)
159
+
160
+ @camera_pivot.yaw(Ogre::Radian.new(Ogre::Degree.new(deltaYaw)), Ogre::Node::TS_WORLD);
161
+
162
+ # bound the pitch
163
+ if (!(@pivot_pitch + deltaPitch > 25 && deltaPitch > 0) &&
164
+ !(@pivot_pitch + deltaPitch < -60 && deltaPitch < 0))
165
+ @camera_pivot.pitch(Ogre::Radian.new(Ogre::Degree.new(deltaPitch)), Ogre::Node::TS_LOCAL)
166
+ @pivot_pitch += deltaPitch;
167
+ end
168
+ dist = @camera_goal._getDerivedPosition().distance(@camera_pivot._getDerivedPosition())
169
+ distChange = deltaZoom * dist;
170
+
171
+ # puts "dist: #{dist}:#{distChange}"
172
+
173
+ # bound the zoom
174
+ if (!(dist + distChange < 8 && distChange < 0) &&
175
+ !(dist + distChange > 25 && distChange > 0))
176
+
177
+ @camera_goal.translate(Ogre::Vector3.new(0, 0, distChange), Ogre::Node::TS_LOCAL)
178
+ end
179
+ end
180
+
181
+ def mouse_pressed(mouseEvent, mouseButtonID)
182
+ @sdk_camera_man.injectMouseDown(mouseEvent, mouseButtonID) if @style == CS_ORBIT
183
+ return true
184
+ end
185
+
186
+ def mouse_released(mouseEvent, mouseButtonID)
187
+ @sdk_camera_man.injectMouseUp(mouseEvent, mouseButtonID) if @style == CS_ORBIT
188
+ return true
189
+ end
190
+
191
+ end
192
+
193
+ end
@@ -0,0 +1,203 @@
1
+ require "teien/garden_object.rb"
2
+ require "teien/light_object.rb"
3
+ require "teien/object_factory.rb"
4
+ require "teien/view.rb"
5
+ #require "teien/server_view.rb"
6
+ require "teien/physics.rb"
7
+ require "teien/user_interface.rb"
8
+ #require "teien/server_user_interface.rb"
9
+
10
+ module Teien
11
+
12
+ # This is a top object of 3D world.
13
+ class Garden
14
+ attr_accessor :view
15
+ attr_accessor :physics
16
+ attr_accessor :resources_cfg
17
+ attr_accessor :plugins_cfg
18
+ attr_accessor :objects
19
+ attr_accessor :object_factory
20
+ attr_accessor :is_server
21
+
22
+ #
23
+ # _script_klass_:: : set a user define class.
24
+ #
25
+ def initialize(script_klass)
26
+ @view = nil
27
+ @physics = nil
28
+ @script_klass = script_klass
29
+
30
+ @resources_cfg = nil
31
+ @plugins_cfg = nil
32
+ @objects = {}
33
+ @object_num = 0
34
+
35
+ @object_factory = ObjectFactory.new(self)
36
+
37
+ @is_server = false
38
+ @debug_draw = false
39
+ @quit = false
40
+ end
41
+
42
+ #
43
+ # set a title name on the window title bar.
44
+ #
45
+ # _title_ :: : set a name(String).
46
+ #
47
+ def set_window_title(title)
48
+ @view.window_title = title unless @is_server
49
+ end
50
+
51
+ #
52
+ # set the gravity of the world.
53
+ #
54
+ # _grav_ :: : set a vector(Vector3D) as the gravity.
55
+ #
56
+ def set_gravity(grav)
57
+ @physics.set_gravity(grav)
58
+ end
59
+
60
+ #
61
+ # set the ambient light of the world.
62
+ #
63
+ # _color_:: : set a color(Color).
64
+ #
65
+ def set_ambient_light(color)
66
+ @view.scene_mgr.setAmbientLight(color)
67
+ end
68
+
69
+ def set_sky_dome(enable, materialName, curvature = 10, tiling = 8, distance = 4000)
70
+ @view.scene_mgr.setSkyDome(enable, materialName, curvature, tiling, distance)
71
+ end
72
+
73
+ def set_debug_draw(bl)
74
+ if (bl)
75
+ @debug_draw = bl
76
+ @debug_drawer = Ogrelet::DebugDrawer.new(@view.scene_mgr)
77
+ @physics.dynamicsWorld.setDebugDrawer(@debug_drawer)
78
+ end
79
+ end
80
+
81
+ def create_user_interface()
82
+ if @is_server
83
+ return ServerUserInterface.new(@view)
84
+ else
85
+ return UserInterface.new(@view)
86
+ end
87
+ end
88
+
89
+ def create_object(name, objectInfo, physicsInfo)
90
+ return @object_factory.create_object(name, objectInfo, physicsInfo)
91
+ end
92
+
93
+ def create_light(name)
94
+ return LightObject.new(self, name)
95
+ end
96
+
97
+ def add_object(obj, collision_filter = nil)
98
+ if (@objects[obj.name] == nil)
99
+ if (obj.rigid_body != nil)
100
+ if (collision_filter)
101
+ @physics.add_rigid_body(obj.rigid_body, collision_filter)
102
+ else
103
+ @physics.add_rigid_body(obj.rigid_body)
104
+ end
105
+ end
106
+ @objects[obj.name] = obj
107
+ obj.id = @object_num
108
+ @object_num += 1
109
+ else
110
+ raise RuntimeError, "There is a object with the same name (#{obj.name})"
111
+ end
112
+ end
113
+
114
+ def check_collision(objectA, objectB)
115
+ result = @physics.contact_pair_test(objectA.rigid_body, objectB.rigid_body)
116
+ return result.isCollided
117
+ end
118
+
119
+ def setup()
120
+ if @is_server
121
+ @view = ServerView.new(self)
122
+ else
123
+ @view = View.new(self)
124
+ end
125
+
126
+ @physics = Physics.new(self)
127
+ @script = @script_klass.new(self)
128
+
129
+ if @view.setup()
130
+ @view.start(@script)
131
+ @view.prepare_render_loop()
132
+
133
+ @physics.setup()
134
+ @script.setup()
135
+
136
+ return true
137
+ else
138
+ return false
139
+ end
140
+ end
141
+
142
+ #
143
+ # mainloop
144
+ #
145
+ def run()
146
+ return false unless setup()
147
+
148
+ last_time = Time.now.to_f
149
+ while !@quit
150
+ now_time = Time.now.to_f
151
+ delta = now_time - last_time
152
+ last_time = now_time
153
+ break unless update(delta)
154
+ end
155
+
156
+ finalize()
157
+
158
+ return true
159
+ end
160
+
161
+
162
+ def update(delta)
163
+ @physics.dynamics_world.debugDrawWorld() if @debug_draw
164
+
165
+ return @view.update(delta)
166
+ end
167
+
168
+ # called from view.update()
169
+ # This function is divided from update() by the purpose of an optimization,
170
+ # which archives to run in parallel with GPU process.
171
+ def updateInFrameRenderingQueued(delta)
172
+ return false unless @physics.update(delta)
173
+
174
+ @objects.each_value {|obj|
175
+ obj.update(delta)
176
+ }
177
+
178
+ return @script.update(delta)
179
+ end
180
+
181
+ def clean_up()
182
+ @physics.finalize()
183
+ @objects = {}
184
+ @view.stop()
185
+ end
186
+
187
+ # called by Garden class.
188
+ # clear all managers.
189
+ def finalize()
190
+ @physics.finalize()
191
+ @view.root.saveConfig()
192
+ @view.finalize()
193
+ @objects = {}
194
+ end
195
+
196
+
197
+ # quit the current running garden.
198
+ def quit()
199
+ @quit = true
200
+ end
201
+ end
202
+
203
+ end # module