Axiom主要的代码大致翻看了下,就想到了自己来模拟一下游戏开发.
这章主要包括创建窗口及3D渲染的一些基本元素,并添加一个第三人称的骨骼动画作主角,加上前文中修改过后的地形组件,能用鼠标和键盘进行漫游.如下图所示.
在Axiom上给出的例子中,可以选择是用OpenGL或是DirectX渲染,现在有问题的地方是如果用OpenGL渲染,而Axiom鼠标与键盘输入采用的是SharpInputSystem,这个在DirectX渲染下是没有问题的,但是在OpenGL渲染的窗口下得不到正确的鼠标位置.而DixectX渲染下,运行一会后,骨骼动画在进行骨骼变化时,调用SoftwareVertexBlend会引起程序挂起,这个问题没找到解决方法,以后在来调.
在上面的情况下,在加上前面我主要学的是OpenGL,我决定在我接下来采用OpenGL渲染以及OpenTK里提供的鼠标与键盘输入接口.
接下来,通过Axiom里提供的例子,结合Samples.Brower.Win32与Samples.Common来看Axiom的渲染流程,结合上面的流程自己写了一半,才发现有现存的,在Axiom.Framework里的Game抽象类里,提供对应流程,因为原始采用SharpInputSystem来处理键盘与鼠标反馈,经过修改,下面是代码.
1 public abstract class Game : IDisposable, IWindowEventListener 2 { 3 protected Root Engine; 4 protected IConfigurationManager ConfigurationManager; 5 protected ResourceGroupManager Content; 6 protected SceneManager SceneManager; 7 protected Camera Camera; 8 protected Viewport Viewport; 9 protected RenderWindow Window; 10 protected Axiom.Graphics.RenderSystem RenderSystem; 11 12 public virtual void Run() 13 { 14 PreInitialize(); 15 LoadConfiguration(); 16 Initialize(); 17 CreateRenderSystem(); 18 CreateRenderWindow(); 19 LoadResource(); 20 CreateSceneManager(); 21 CreateCamera(); 22 CreateViewports(); 23 CreateInput(); 24 CreateScene(); 25 this.Engine.StartRendering(); 26 } 27 28 private void PreInitialize() 29 { 30 this.ConfigurationManager = new DefaultConfigurationManager(); 31 32 // instantiate the Root singleton 33 this.Engine = new Root(this.ConfigurationManager.LogFilename); 34 35 // add event handlers for frame events 36 this.Engine.FrameStarted += Engine_FrameRenderingQueued; 37 } 38 39 public virtual void LoadConfiguration() 40 { 41 this.ConfigurationManager.RestoreConfiguration(this.Engine); 42 } 43 44 45 private void Engine_FrameRenderingQueued(object source, FrameEventArgs e) 46 { 47 Update(e.TimeSinceLastFrame); 48 } 49 50 public virtual void Initialize() 51 { 52 } 53 54 public virtual void CreateRenderSystem() 55 { 56 if (this.Engine.RenderSystem == null) 57 { 58 this.RenderSystem = this.Engine.RenderSystem = this.Engine.RenderSystems.First().Value; 59 } 60 else 61 { 62 this.RenderSystem = this.Engine.RenderSystem; 63 } 64 } 65 66 public virtual void CreateRenderWindow() 67 { 68 this.Window = Root.Instance.Initialize(true, "Xin Game"); 69 70 WindowEventMonitor.Instance.RegisterListener(this.Window, this); 71 } 72 73 public virtual void LoadResource() 74 { 75 ResourceGroupManager.Instance.InitializeAllResourceGroups(); 76 } 77 78 public virtual void CreateSceneManager() 79 { 80 // Get the SceneManager, a generic one by default 81 this.SceneManager = this.Engine.CreateSceneManager("DefaultSceneManager", "GameSMInstance"); 82 this.SceneManager.ClearScene(); 83 } 84 85 public virtual void CreateCamera() 86 { 87 // create a camera and initialize its position 88 this.Camera = this.SceneManager.CreateCamera("MainCamera"); 89 this.Camera.Position = new Vector3(0, 0, 0); 90 this.Camera.LookAt(new Vector3(0, 0, -300)); 91 92 } 93 94 public virtual void CreateViewports() 95 { 96 // create a new viewport and set it's background color 97 this.Viewport = this.Window.AddViewport(this.Camera, 0, 0, 1.0f, 1.0f, 100); 98 this.Viewport.BackgroundColor = ColorEx.SteelBlue; 99 } 100 101 public virtual void CreateInput() 102 { 103 //var window = this.Window["nativewindow"]; 104 } 105 106 public abstract void CreateScene(); 107 108 public virtual void Update(float timeSinceLastFrame) 109 { 110 } 111 112 #region IDisposable Implementation 113 114 #region IsDisposed Property 115 116 /// <summary> 117 /// Determines if this instance has been disposed of already. 118 /// </summary> 119 public bool IsDisposed { get; set; } 120 121 #endregion IsDisposed Property 122 123 /// <summary> 124 /// Class level dispose method 125 /// </summary> 126 /// <remarks> 127 /// When implementing this method in an inherited class the following template should be used; 128 /// protected override void dispose( bool disposeManagedResources ) 129 /// { 130 /// if ( !IsDisposed ) 131 /// { 132 /// if ( disposeManagedResources ) 133 /// { 134 /// // Dispose managed resources. 135 /// } 136 /// 137 /// // If there are unmanaged resources to release, 138 /// // they need to be released here. 139 /// } 140 /// 141 /// // If it is available, make the call to the 142 /// // base class's Dispose(Boolean) method 143 /// base.dispose( disposeManagedResources ); 144 /// } 145 /// </remarks> 146 /// <param name="disposeManagedResources">True if Unmanaged resources should be released.</param> 147 protected virtual void dispose(bool disposeManagedResources) 148 { 149 if (!IsDisposed) 150 { 151 if (disposeManagedResources) 152 { 153 if (this.Engine != null) 154 { 155 // remove event handlers 156 this.Engine.FrameStarted -= Engine_FrameRenderingQueued; 157 } 158 if (this.SceneManager != null) 159 { 160 this.SceneManager.RemoveAllCameras(); 161 } 162 this.Camera = null; 163 if (Root.Instance != null) 164 { 165 Root.Instance.RenderSystem.DetachRenderTarget(this.Window); 166 } 167 if (this.Window != null) 168 { 169 WindowEventMonitor.Instance.UnregisterWindow(this.Window); 170 this.Window.Dispose(); 171 } 172 if (this.Engine != null) 173 { 174 this.Engine.Dispose(); 175 } 176 } 177 178 // There are no unmanaged resources to release, but 179 // if we add them, they need to be released here. 180 } 181 IsDisposed = true; 182 } 183 184 /// <summary> 185 /// Call to when class is no longer needed 186 /// </summary> 187 public void Dispose() 188 { 189 dispose(true); 190 GC.SuppressFinalize(this); 191 } 192 193 ~Game() 194 { 195 dispose(false); 196 } 197 198 #endregion IDisposable Implementation 199 200 #region IWindowEventListener Implementation 201 202 /// <summary> 203 /// Window has moved position 204 /// </summary> 205 /// <param name="rw">The RenderWindow which created this event</param> 206 public void WindowMoved(RenderWindow rw) 207 { 208 } 209 210 /// <summary> 211 /// Window has resized 212 /// </summary> 213 /// <param name="rw">The RenderWindow which created this event</param> 214 public void WindowResized(RenderWindow rw) 215 { 216 } 217 218 /// <summary> 219 /// Window has closed 220 /// </summary> 221 /// <param name="rw">The RenderWindow which created this event</param> 222 public void WindowClosed(RenderWindow rw) 223 { 224 // Only do this for the Main Window 225 if (rw == this.Window) 226 { 227 Root.Instance.QueueEndRendering(); 228 } 229 } 230 231 /// <summary> 232 /// Window lost/regained the focus 233 /// </summary> 234 /// <param name="rw">The RenderWindow which created this event</param> 235 public void WindowFocusChange(RenderWindow rw) 236 { 237 } 238 239 #endregion 240 }