//准备退出,销毁包括device在内的一切资源:D3D/Win32/Device public void CleanupGraphics() { //D3D资源 ToDispose(ms.mesh); ms.mesh = null; ToDispose(ws.mesh); ws.mesh = null; ToDispose(pl.vertexbuf); pl.vertexbuf = null; ToDispose(wpl.vertexbuf); wpl.vertexbuf = null; //一体Dispose sl及其VertexBuffer ToDispose(sl); sl = null; //销毁所有D3D字体 ToDispose(d3dfont_selected); d3dfont_selected = null; ToDispose(d3dfont_hud); d3dfont_hud = null; ToDispose(sprite); sprite = null; //销毁精灵 ToDispose(bkground_hud); bkground_hud = null; //销毁信息框背景相关的一切资源 //Win32资源 ToDispose(font_selected); font_selected = null; ToDispose(font_hud); font_hud = null; ToDispose(bmp_hud); bmp_hud = null; //Device ToDispose(device); device = null; }
//////////////////////////////////////////////////////////////////////////////////// //重建除device之外的一切D3D资源 public void SetupDevice() { //重建所有的Mesh if (ms.mesh == null) { ms.CreateExtrusionMesh(device); } if (ws.mesh == null) { ws.CreateWallMesh(device); } //重建所有的VertexBuffer if (pl.vertexbuf == null) { pl.CreatePartitionLinesVertexBuffer(device); } if (wpl.vertexbuf == null) { wpl.CreateWallPartitionLinesVertexBuffer(device); } //一体创建sl及其VertexBuffer if (sl == null) { sl = new SelectionLines(ms.polys[curr_district]); sl.CreateSelectionLines(device); } ////创建显示所需的字体 if (d3dfont_selected == null) { d3dfont_selected = new Microsoft.DirectX.Direct3D.Font(device, font_selected); } if (d3dfont_hud == null) { d3dfont_hud = new Microsoft.DirectX.Direct3D.Font(device, font_hud); } //设置信息框背景贴图 if (bkground_hud == null) { bkground_hud = new Texture(device, bmp_hud, Usage.Dynamic, Pool.Default); } //创建显示信息框的精灵 if (sprite == null) { sprite = new Sprite(device); } }
//////////////////////////////////////////////////////////////////////////////////// protected void OnDeviceLost(object sender, EventArgs e) { //释放除device外所有D3D资源 ToDispose(ms.mesh); ms.mesh = null; ToDispose(ws.mesh); ws.mesh = null; ToDispose(pl.vertexbuf); pl.vertexbuf = null; ToDispose(wpl.vertexbuf); wpl.vertexbuf = null; //一体Dispose sl及其VertexBuffer ToDispose(sl); sl = null; //销毁所有D3D字体 ToDispose(d3dfont_selected); d3dfont_selected = null; ToDispose(d3dfont_hud); d3dfont_hud = null; ToDispose(sprite); sprite = null; //销毁精灵 ToDispose(bkground_hud); bkground_hud = null; //销毁信息框背景相关的一切资源 }
//////////////////////////////////////////////////////////////////////////////////// #region Picking System相关 bool Picking(int sx, int sy) { float P11 = device.Transform.Projection.M11; float P22 = device.Transform.Projection.M22; //screen到projection平面,相当于首先抵消projection变换 float px = ((2F * sx) / client_size.Width - 1F) / P11; float py = ((-2F * sy) / client_size.Height + 1F) / P22; float pz = 1F; Vector3 ray_pos = new Vector3(0F, 0F, 0F); Vector3 ray_dir = new Vector3(px, py, pz); //抵消world和view变换 Matrix invert = Matrix.Invert(device.Transform.World * device.Transform.View); //最后计算在world中的射线 ray_pos.TransformCoordinate(invert); ray_dir.TransformNormal(invert); ray_dir.Normalize(); //计算ray与ms的相交多边形 int polyid = ms.MatchPicking(device, ray_pos, ray_dir); if (polyid == -1) { return(false); } else { curr_district = polyid; sl.Dispose(); sl = new SelectionLines(ms.polys[curr_district]); sl.CreateSelectionLines(device); } return(true); }
//////////////////////////////////////////////////////////////////////////////////// void Game_KeyDown(object sender, KeyEventArgs e) { switch (e.KeyCode) { case Keys.C: EnableColoring = !EnableColoring; EnableLights = false; ms.mesh.Dispose(); ms = new ExtrusionMesh(sec, Color.White, EnableColoring); ms.CreateExtrusionMesh(device); break; case Keys.Escape: case Keys.Q: Close(); break; case Keys.K: //距离 //地图越大,将距离调最远时,越容易出现被culling的现象,估计跟projection有关 camera.IncreaseRadius(100F); //if (scaling + 0.1F <= 5) scaling += 0.1f; break; case Keys.J: //距离 camera.DecreaseRadius(100F); //if (scaling - 0.1F >= 0.1) scaling -= 0.1f; break; case Keys.Left: //视角 camera.DecreaseLongitude((float)(0.02 * Math.PI)); break; case Keys.Right: //视角 camera.IncreaseLongitude((float)(0.02 * Math.PI)); break; case Keys.Up: //视角 camera.IncreaseLatitude((float)(0.02F * Math.PI)); break; case Keys.Down: //视角 camera.DecreaseLatitude((float)(0.02F * Math.PI)); break; case Keys.Z: //光线方向 dir_light.AdjustLongitude((float)(-0.02 * Math.PI)); break; case Keys.X: //光线方向 dir_light.AdjustLongitude((float)(0.02 * Math.PI)); break; case Keys.A: //光线方向 dir_light.AdjustLatitude((float)(0.02 * Math.PI)); break; case Keys.S: //光线方向 dir_light.AdjustLatitude((float)(-0.02 * Math.PI)); break; case Keys.F: //区域线框 DisplayWireFrame = !DisplayWireFrame; break; case Keys.L: //光照开关 EnableLights = !EnableLights; break; case Keys.H: //水平面开关 DisplayHorizonalMesh = !DisplayHorizonalMesh; break; case Keys.V: //垂直面开关 DisplayVerticalMesh = !DisplayVerticalMesh; break; case Keys.I: DisplayInfoHUD = !DisplayInfoHUD; break; case Keys.R: //复位world平移矢量和camera半径 world_translation = center; camera.ResetRadius(); break; #if (!FULL_SCREEN) case Keys.O: string fn = Program.SelectSecFile(); if (fn != null) { //从头创建所有的一切! CleanupGraphics(); GC.Collect(); ResetAll(fn); InitializeGraphics(); } break; #endif case Keys.OemPeriod: curr_district = (curr_district + 1) % ms.polys.Length; sl.Dispose(); sl = new SelectionLines(ms.polys[curr_district]); sl.CreateSelectionLines(device); curr_centroid = ms.polys[curr_district].GetCentroid(); GenerateMessageString(); break; case Keys.Oemcomma: curr_district = (curr_district + ms.polys.Length - 1) % ms.polys.Length; sl.Dispose(); sl = new SelectionLines(ms.polys[curr_district]); sl.CreateSelectionLines(device); curr_centroid = ms.polys[curr_district].GetCentroid(); GenerateMessageString(); break; default: Debug.WriteLine(e.KeyCode); break; } }
//////////////////////////////////////////////////////////////////////////////////// void ResetAll(string fn) { //////////////////////////////////////////////////////////////////////////////////// //所有关键变量的清空和初始化 EnableColoring = true; EnableLights = false; DisplayWireFrame = true; DisplayHorizonalMesh = true; DisplayVerticalMesh = true; DisplayInfoHUD = true; //挤压Mesh的球面中心点 center = new Vector3(); //当前选中的多边形编号及其质心 curr_district = 0; curr_centroid = new Vector3(); //world中的平移矢量 world_translation = new Vector3(); //其值要么等于center,要么等于当前选择的面质心坐标 //World等比放大系数,暂时不用 scaling = 1F; //Direct3D相关 device = null; device_lost = false; present_params = null; batch = 0; //Direct3D资源相关 font_selected = font_hud = null; d3dfont_selected = d3dfont_hud = null; bmp_hud = null; bkground_hud = null; sprite = null; //显示信息相关 filename = message = null; //窗口状态相关 onpaint_enabled = true; //////////////////////////////////////////////////////////////////////////////////// //生成原始数据和所有点、面和线框 sec = new Sec(fn); ms = new ExtrusionMesh(sec, Color.White, EnableColoring); ws = new WallMesh(sec, Color.Gainsboro); pl = new PartitionLines(ms.polys, Color.Red); wpl = new WallPartitionLines(sec, Color.Blue); //对sl采取的管理策略是不同的,其VertexBuffer和其自身将被同时创建或删除 //这里无需初始化,InitializeGraphics中自然会初始化 sl = null; //初始化当前选中的多边形的质心 curr_centroid = ms.polys[curr_district].GetCentroid(); //设置标题栏 FileInfo fi = new FileInfo(fn); filename = fn; // fi.Name.ToLower(); Text = "3D .Sec Viewer - " + filename; //初始化信息字符串 GenerateMessageString(); }