学习OGRE有一段时间了,领导为了检测学习效果,根据已有C++项目,弄一个类似的用c#语言编写的小项目。
配置:win7,DirectX2009,vs2010.
项目要求:
1.有Ogre窗口(尺寸1600*900),周围有导航按钮(分别进行旋转拉伸平移操作)
2.导入VIV手臂模型(左右手),默认只显示左手,通过按钮可以进行模型切换显示
3.模型上有完整贴图,点光源绑在照相机上
4.Ogre窗口中开小Viewport,从正上方俯视整条手臂
5.导入消毒动画,并实现手背上消毒效果(本来就是对齐的)
6.导入小垫枕模型,可以通过wasd按键控制其以后
7.通过点击按钮能实现手臂更换贴图
编写时遇到的问题:
1、在新建完项目工程winform后,需要对winform进行配置,此过程中本来是想走捷径, 使用以前拷贝的cfg文件直接添加到项目中(半个月前使用过此方法成功创建项目),导致有错误出现。
2、在设置手臂材料时,最好是新建一个material文件夹。 (设置左手臂时,在以前练习文件的基础上添加左臂材质,始终没有成功, 原因可能是后来的材质带有片段和顶点着色器,而本次没有设置)
实现过程:
1导航按钮
旋转:nodeRoot.Pitch(new Radian(0.5f)); 平移: 左移右移,nodeRoot.Position += new Vector3(-5, 0, 0); nodeRoot.Position += new Vector3(10, 0, 0);
2 导入模型:
将mesh导入到model文件夹中,在代码中引用即可,同时设置材质
entLArm = sceneMgr.CreateEntity("leftArm", "A_N_Y_F_LH_S.mesh");
SceneNode nodeLArm = sceneMgr.CreateSceneNode("nodelarm");
nodeRoot.AddChild(nodeLArm);
nodeLArm.AttachObject(entLArm);
nodeLArm.SetPosition(0, 0, 0);
entLArm.SetMaterialName("LArmMaterial");
entLArm.Visible = showLArm;
3 将点光源绑定到照相机上 定义一个照相机,同时创建一个视口。创建一个节点,将照相机和光源都绑定到此节点即可实现此功能。
SceneNode nodeCam1 = sceneMgr.CreateSceneNode("nodecam");
nodeCam1.AttachObject(cam1);
nodeCam1.AttachObject(light1);
4 开一小窗口 因为视角不同,所以新建一个照相机和视口,即可实现。
cam1 = sceneMgr.CreateCamera("Camera1");
cam1.AutoAspectRatio = true;
cam1.Position = new Vector3(0,0,300);
cam1.LookAt(0, 0, 0);
Viewport vp1 = rWindow.AddViewport(cam1,0,0,0,1,1);
vp1.BackgroundColour = ColourValue.White;
cam2 = sceneMgr.CreateCamera("Camera2");
cam2.AutoAspectRatio = true;
cam2.Position = new Vector3(-50, 300, 0);
cam2.LookAt(0, 0, 0);
Viewport vp2 = rWindow.AddViewport(cam2,1,0,0,0.2f,0.3f);
vp2.BackgroundColour = ColourValue.Black;
5 导入消毒动画 将消毒动画文件skeleton放入项目文件中,并设置动画状态。
entDisinfection = sceneMgr.CreateEntity("disinfection", "Disinfection_big.mesh");
animaStateDis = entDisinfection.GetAnimationState("Disinfection_big");
animaStateDis.Enabled = false;
animaStateDis.Loop = true;
并在帧监听中添加:
if (animaStateDis != null)
{
animaStateDis.AddTime(evt.timeSinceLastFrame);
}
6 加入垫枕模型,并用wasd键移动它 写入键盘事件:
首先设置:
private void Form1_Load(object sender, EventArgs e)
{
this.KeyPreview = true;
this.KeyPress += new KeyPressEventHandler(Form1_KeyPress);
}
void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.KeyUp += new KeyEventHandler(Form1_KeyUp);
}
void Form1_KeyUp(object sender, KeyEventArgs e)
{
}
void Form1_KeyDown(object sender, KeyEventArgs e)
{
}
7 更换贴图
实际就是更换材质。将其材质放在帧监听中
switch (stateMaterial)
{
case 1:
entLArm.SetMaterialName("LArmMaterial");
break;
case 2:
entLArm.SetMaterialName("BLArmMaterial");
break;
default :
entLArm.SetMaterialName("LArmMaterial");
break;
}
完整的代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Mogre; using MogreFramework; namespace MOGREWinform { public partial class Form1 : Form { public Form1() { InitializeComponent(); //release resource Disposed += new EventHandler(Form1_Disposed); } //dispose resource void Form1_Disposed(object sender, EventArgs e) { this.dispose1(); } public void dispose1() { if (mRoot != null) { mRoot.Dispose(); mRoot = null; } } Root mRoot; RenderWindow rWindow; SceneManager sceneMgr; Camera cam1; Camera cam2; SceneNode nodeRoot; SceneNode nodePillow; Light light1; Entity entLArm; Entity entRArm; Entity entDisinfection; bool showLArm = true;//default show left arm bool showRArm = false;//show right arm bool mRotating = false;// mouse rotate Point mLastPosition; float Rotate = 0.2f; int stateMaterial = 0;//arm 1:left yellow,2:left black,3:right yellow,4:right black,5:disinfection AnimationState animaStateDis;//disinfection animationstate //set up initialize public void init() { //create root object mRoot = new Root(); // Define Resources ConfigFile cf = new ConfigFile(); cf.Load("resources.cfg", " :=", true); ConfigFile.SectionIterator seci = cf.GetSectionIterator(); String secName, typeName, archName; while (seci.MoveNext()) { secName = seci.CurrentKey; ConfigFile.SettingsMultiMap settings = seci.Current; foreach (KeyValuePair<string, string> pair in settings) { typeName = pair.Key; archName = pair.Value; ResourceGroupManager.Singleton.AddResourceLocation(archName, typeName, secName); } } //set up Rendersystem RenderSystem rs = mRoot.GetRenderSystemByName("Direct3D9 Rendering Subsystem"); mRoot.RenderSystem = rs; rs.SetConfigOption("Full Screen", "No"); rs.SetConfigOption("Video Mode", "800 x 600 @ 32-bit colour"); //create Render Window mRoot.Initialise(false, "Main Ogre Window"); NameValuePairList misc = new NameValuePairList(); //将panel1作为渲染容器 misc["externalWindowHandle"] = this.panel1.Handle.ToString(); rWindow = mRoot.CreateRenderWindow("Main RenderWindow", 800, 600, false, misc); //Init resources TextureManager.Singleton.DefaultNumMipmaps = 5; ResourceGroupManager.Singleton.InitialiseAllResourceGroups(); // sceneMgr = mRoot.CreateSceneManager(SceneType.ST_GENERIC); //set nodeRoot nodeRoot = sceneMgr.CreateSceneNode("node0"); sceneMgr.RootSceneNode.AddChild(nodeRoot);//important nodeRoot.Position = new Vector3(0, 0, 0); //nodeRoot.SetPosition(0, 0, 0); //set up camera,viewport cam1 = sceneMgr.CreateCamera("Camera1"); cam1.AutoAspectRatio = true; cam1.Position = new Vector3(0,0,300); cam1.LookAt(0, 0, 0); Viewport vp1 = rWindow.AddViewport(cam1,0,0,0,1,1); vp1.BackgroundColour = ColourValue.White; cam2 = sceneMgr.CreateCamera("Camera2"); cam2.AutoAspectRatio = true; cam2.Position = new Vector3(-50, 300, 0); cam2.LookAt(0, 0, 0); Viewport vp2 = rWindow.AddViewport(cam2,1,0,0,0.2f,0.3f); vp2.BackgroundColour = ColourValue.Black; light1 = sceneMgr.CreateLight("light1"); light1.Type = Light.LightTypes.LT_POINT; light1._setCameraRelative(cam1); light1.Position = new Vector3(0, 0, 300); light1.SetDiffuseColour(1, 0, 0); SceneNode nodeCam1 = sceneMgr.CreateSceneNode("nodecam"); //nodeRoot.AddChild(nodeCam1); nodeCam1.AttachObject(cam1); nodeCam1.AttachObject(light1); //FrameListener mRoot.FrameStarted += new FrameListener.FrameStartedHandler(mRoot_FrameStarted); this .panel1 .MouseDown +=new MouseEventHandler(panel1_MouseDown); this.panel1.MouseUp += new MouseEventHandler(panel1_MouseUp); this.panel1.MouseMove += new MouseEventHandler(panel1_MouseMove); } void panel1_MouseMove(object sender, MouseEventArgs e) { if (mRotating) { float x = mLastPosition.X - Cursor.Position.X; float y = mLastPosition.Y - Cursor.Position.Y; cam1.Yaw(new Degree(x * Rotate)); cam1.Pitch(new Degree(y * Rotate)); mLastPosition = Cursor.Position; } } void panel1_MouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Cursor.Show(); mRotating = false; } } void panel1_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { Cursor.Hide(); mRotating = true; mLastPosition = Cursor.Position; } } bool mRoot_FrameStarted(FrameEvent evt) { //change arm if (showLArm == true) { entLArm.Visible = true; entRArm.Visible = false; } else { entRArm.Visible = true; entLArm.Visible = false; } // switch (stateMaterial) { case 1: entLArm.SetMaterialName("LArmMaterial"); break; case 2: entLArm.SetMaterialName("BLArmMaterial"); break; case 3: entRArm.SetMaterialName("RArmMaterial"); break; case 4: entRArm.SetMaterialName("BRArmMaterial"); break; case 51: entLArm.SetMaterialName("DisinfectionMaterial"); break; case 53: entRArm.SetMaterialName("DisinfectionMaterial"); break; default : entLArm.SetMaterialName("LArmMaterial"); break; } //disinfection animation if (animaStateDis != null) { animaStateDis.AddTime(evt.timeSinceLastFrame); } return true; } public void run() { Show(); while (mRoot != null && mRoot.RenderOneFrame()) { Application.DoEvents(); } } //close the Form1 private void btClose_Click(object sender, EventArgs e) { this.Close(); } //import left arm public void importLArm() { entLArm = sceneMgr.CreateEntity("leftArm", "A_N_Y_F_LH_S.mesh"); SceneNode nodeLArm = sceneMgr.CreateSceneNode("nodelarm"); nodeRoot.AddChild(nodeLArm); nodeLArm.AttachObject(entLArm); nodeLArm.SetPosition(0, 0, 0); //entLArm.SetMaterialName("LArmMaterial"); entLArm.Visible = showLArm; } //import right arm public void importRArm() { entRArm = sceneMgr.CreateEntity("rightArm", "A_N_Y_F_RH_S.mesh"); SceneNode nodeRArm = sceneMgr.CreateSceneNode("noderarm"); nodeRoot.AddChild(nodeRArm); nodeRArm.AttachObject(entRArm); //entRArm.SetMaterialName("RArmMaterial"); entRArm.Visible = showRArm; } //change arm private void btChangeArm_Click(object sender, EventArgs e) { if (showLArm == true) { showLArm = false; showRArm = true; stateMaterial = 3; } else { showRArm = false; showLArm = true; stateMaterial = 1; } } private void Form1_Load(object sender, EventArgs e) { importLArm(); importRArm(); this.KeyPreview = true; this.KeyPress += new KeyPressEventHandler(Form1_KeyPress); } #region wasd control void Form1_KeyPress(object sender, KeyPressEventArgs e) { this.KeyDown += new KeyEventHandler(Form1_KeyDown); this.KeyUp += new KeyEventHandler(Form1_KeyUp); } void Form1_KeyUp(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.W: case Keys.S: case Keys.A: case Keys.D: nodePillow.Position += new Vector3(0, 0, 0); break; } } void Form1_KeyDown(object sender, KeyEventArgs e) { if (nodePillow != null) { switch (e.KeyCode) { case Keys.W: nodePillow.Position += new Vector3(0, 0, -0.05f); break; case Keys.S: nodePillow.Position += new Vector3(0, 0, 0.02f); break; case Keys.A: nodePillow.Position += new Vector3(-0.02f, 0, 0); break; case Keys.D: nodePillow.Position += new Vector3(0.02f, 0, 0); break; } } } #endregion //rotate private void btRotate_Click(object sender, EventArgs e) { nodeRoot.Pitch(new Radian(0.5f)); } //stretch private void btStretch_Click(object sender, EventArgs e) { } //Translation private void btLTranslation_Click(object sender, EventArgs e) { nodeRoot.Position += new Vector3(-5, 0, 0); } private void btRTranslation_Click(object sender, EventArgs e) { nodeRoot.Position += new Vector3(10, 0, 0); } //add pillow private void btAddPillow_Click(object sender, EventArgs e) { Entity entPillow = sceneMgr.CreateEntity("entpillow", "Pillow2.mesh"); nodePillow = sceneMgr.CreateSceneNode("nodepillow"); nodeRoot.AddChild(nodePillow); nodePillow.AttachObject(entPillow); entPillow.SetMaterialName("Pillow2"); this.btAddPillow.Enabled = false; } //change the material private void btChangeMap_Click(object sender, EventArgs e) { if (entLArm.Visible == true) { if ((stateMaterial == 1)||(stateMaterial == 0)) { stateMaterial = 2; } else { stateMaterial = 1; } } else { if (stateMaterial == 3) { stateMaterial = 4; } else { stateMaterial = 3; } } } //disinfection private void cbDisinfection_CheckedChanged(object sender, EventArgs e) { if (animaStateDis != null) { if (cbDisinfection.Checked) { if (animaStateDis != null) { animaStateDis.Enabled = true; } } else { animaStateDis.Enabled = false; entDisinfection.Visible = false; switch (stateMaterial) { case 1: case 2: stateMaterial = 51; break; case 3: case 4: default: stateMaterial = 53; break; } } } else { MessageBox.Show("没有消毒棒!"); cbDisinfection.Checked = false; } } //add stick private void btAddStick_Click(object sender, EventArgs e) { entDisinfection = sceneMgr.CreateEntity("disinfection", "Disinfection_big.mesh"); SceneNode nodeDisifection = sceneMgr.CreateSceneNode("nodedisifection"); nodeRoot.AddChild(nodeDisifection); nodeDisifection.AttachObject(entDisinfection); nodeDisifection.Position = new Vector3(100, 18, 0); this.btAddStick.Enabled = false; animaStateDis = entDisinfection.GetAnimationState("Disinfection_big"); animaStateDis.Enabled = false; animaStateDis.Loop = true; } private void btTwodisinfection_Click(object sender, EventArgs e) { entDisinfection.Visible = true; } //private void btAddBaby_Click(object sender, EventArgs e) //{ // Entity entBaby = sceneMgr.CreateEntity("baby", "VIV1.1_head_baby.mesh"); // SceneNode nodeBaby = sceneMgr.CreateSceneNode("nodebaby"); // nodeRoot.AddChild(nodeBaby); // nodeBaby.AttachObject(entBaby); // entBaby.SetMaterialName("VIV1.1_head_baby"); // //nodeBaby.Scale(5, 5, 5); // this.btAddBaby.Enabled = false; //} } }
总结:虽然是一个很小很小的项目,还是有一点体悟:
1、纸上得来终觉浅,绝知此事要躬行。事前感觉到很简单的事,做起来可能制造点麻烦。
2、理解需求很重要。深入、正确的理解需求,后来编写代码事半功倍。
3、思路。思路很重要,如果思路不对,问题永远是不可能解决的。