Ogre 용 SceneEditor 제작중
내 일상 2009. 3. 13. 03:15 |요즘 Ogre용 개발을 위한 씬 에디터를 제작 중이다.
아직 기본 틀만 잡힌 상태며, MOgre 1.4 버젼을 사용해서 C#, Winform을 사용해서 구현하고 있다.
protected bool mLMBDown = false;
const float ROTATE = 0.2f;
const float TRANSLATE = 1;
Point mLastPosition;
Vector3 mTranslation = Vector3.ZERO;
.....
void mogrepanel_MouseDown(object sender, MouseEventArgs e)
{
mLMBDown = true;
mLastPosition = e.Location;
}
void mogrepanel_MouseUp(object sender, MouseEventArgs e)
{
mLMBDown = false;
}
void mogrepanel_MouseMove(object sender, MouseEventArgs e)
{
mTranslation = Vector3.ZERO;
if (e.Button == MouseButtons.Left)
{
float x = mLastPosition.X - e.Location.X;
float y = mLastPosition.Y - e.Location.Y;
// 화면을 Dolly 모드 처럼 구현하기
mogreWin.camera.Yaw(new Degree(x * ROTATE));
mogreWin.camera.Pitch(new Degree(y * ROTATE));
}
else if (e.Button == MouseButtons.Right)
{
float y = mLastPosition.Y - e.Location.Y;
mTranslation.z = y * TRANSLATE;
// 화면을 줌인, 줌아웃 처리 하는 것
mogreWin.camera.Position += mogreWin.camera.Orientation * mTranslation;
}
else if (e.Button == MouseButtons.Middle)
{
float x = mLastPosition.X - e.Location.X;
float y = mLastPosition.Y - e.Location.Y;
mTranslation.x = x * TRANSLATE;
mTranslation.y = -(y * TRANSLATE);
// 화면을 좌우상하 움직이는 것
mogreWin.camera.Position += mTranslation;
}
mogreWin.Paint();
mLastPosition = e.Location;
}
윈폼에서 3D 뷰에서 객체를 선택하는 로직이다.
아무래도 바운딩 박스 구조로 선택이 되는거 같다.
void mogrepanel_MouseDown(object sender, MouseEventArgs e)
{
mLMBDown = true;
mLastPosition = e.Location;
// 히트 테스트
mogreWin.ClickedOnHead(e.X, e.Y);
}
.....
public bool ClickedOnHead(int mx, int my)
{
float scrx = (float)mx / viewport.ActualWidth;
float scry = (float)my / viewport.ActualHeight;
Ray ray = camera.GetCameraToViewportRay(scrx, scry);
RaySceneQuery query = sceneMgr.CreateRayQuery(ray);
RaySceneQueryResult results = query.Execute();
boxsceneNode.ShowBoundingBox = false;
sceneNode.ShowBoundingBox = false;
foreach (RaySceneQueryResultEntry entry in results)
{
if (entry.movable.Name == "ogre")
{
//boxsceneNode.ShowBoundingBox = false;
sceneNode.ShowBoundingBox = true;
}
else if (entry.movable.Name == "box")
{
//sceneNode.ShowBoundingBox = false;
boxsceneNode.ShowBoundingBox = true;
}
// 위의 entry.movable.Name 를 사용해서 적당하게 처리 하면 될듯 하다.
}
return results.Count > 0;
}
private void CreateGrid(int numcols, int numrows, float unitsize)
{
// 생성
ManualObject grid = sceneMgr.CreateManualObject("grid");
grid.Begin("BaseWhiteNoLighting", RenderOperation.OperationTypes.OT_LINE_LIST);
float width = (float)numcols * unitsize;
float depth = (float)numrows * unitsize;
Vector3 center = new Vector3(-width / 2.0f, 0, -depth / 2.0f);
for (int i = 0; i < numrows; ++i)
{
Vector3 s, e;
s.x = 0.0f;
s.z = i * unitsize;
s.y = 0.0f;
e.x = width;
e.z = i * unitsize;
e.y = 0.0f;
grid.Position(s + center);
grid.Position(e + center);
}
grid.Position(new Vector3(0.0f, 0.0f, numrows * unitsize) + center);
grid.Position(new Vector3(width, 0.0f, numrows * unitsize) + center);
for (int i = 0; i < numcols; ++i)
{
Vector3 s, e;
s.x = i * unitsize;
s.z = depth;
s.y = 0.0f;
e.x = i * unitsize;
e.z = 0.0f;
e.y = 0.0f;
grid.Position(s + center);
grid.Position(e + center);
}
grid.Position(new Vector3(numcols * unitsize, 0.0f, 0.0f) + center);
grid.Position(new Vector3(numcols * unitsize, 0.0f, depth) + center);
grid.End();
sceneMgr.RootSceneNode.AttachObject(grid);
}
윈폼의 UI 기반의 코드를 작성하다 보면
3D의 화면은 사이즈가 빈번하게 변경된다.
이때 뷰포트와 카메라의 비율은 변경을 해주어야 한다.
아래의 코드는 그 일부분이다.
protected RenderWindow window;
public Camera camera;
protected Viewport viewport;
.......
// 윈도우 사이즈가 변하면 여기서 WindowMovedOrResized 메소드를 호출해 주어야 한다.
window.WindowMovedOrResized();
// 호출후에 생성된 윈도우 사이즈를 SetConfigOption()에 추가해 주어야 한다.
string videomode = string.Format("{0} x {1} @ 32-bit colour", window.Width, window.Height);
root.RenderSystem.SetConfigOption("Video Mode", videomode);
// 카메라의 비율을 재 생성한다.
camera.AspectRatio = ((float)viewport.ActualWidth) / ((float)viewport.ActualHeight);