카테고리 없음 2010. 6. 24. 10:44

3D객체 마우스컨트롤 / HIT TEST

 

GameObject.cs

namespace Sample3D_1

{

    class GameObject

    {

        public Model model = null;

        public Vector3 position = Vector3.Zero;

        public Vector3 rotation = Vector3.Zero;

        public float scale = 1.0f;

 

        public bool clickme = false;

        public bool collision = true;

    }

}

 

Game.cs

GameObject[] obj = new GameObject[5];

 

        Vector3 cameraPosition = new Vector3(0.0f, 60.0f, 160.0f);

        Vector3 cameraLookAt = new Vector3(0.0f, 0.0f, 0.0f);

 

        Matrix cameraProjectionMatrix;

        Matrix cameraViewMatrix;

 

        MouseState ms;

        MouseState prevMouse;

 

        Vector3 PrevPosition = Vector3.Zero;

           protected override void LoadContent()

        {

            spriteBatch = new SpriteBatch(GraphicsDevice);

            cameraViewMatrix = Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);

            cameraProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f),

                graphics.GraphicsDevice.Viewport.AspectRatio, 1.0f, 10000.0f);

 

            for (int i = 0; i < 5; i++)

            {

                obj[i] = new GameObject();

                obj[i].model = Content.Load<Model>("Models\\brownFire");

            }

 

            obj[1].position.X = obj[0].position.X + 40.0f;

            obj[2].position.X = obj[0].position.X - 40.0f;

            obj[3].position.Y = obj[0].position.Y + 40.0f;

            obj[4].position.Y = obj[0].position.Y - 40.0f;

        }

protected override void Update(GameTime gameTime)

        {

            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)

                this.Exit();

            ms = Mouse.GetState();

            for (int i = 0; i < 5; i++)

            {

                MouseCheck(obj[i]);

//클릭한 곳에 3d객체가 존제하는지 체크 존재한다면 속성을 true

                KeyboardCheck(obj[i]);

                if (obj[i].clickme)

                {

                    PrevPosition = obj[i].position;

                    MouseControl(obj[i]);

                    testcollision(obj[i]);

                }

            }

            prevMouse = ms;

        }

           private void testcollision(GameObject firefall)

        {

            BoundingSphere bs = firefall.model.Meshes[0].BoundingSphere;

            bs.Center = firefall.position;

            foreach (GameObject fire in obj)

            {

                if (!fire.clickme)

                {

                    BoundingSphere bs2 = fire.model.Meshes[0].BoundingSphere;

                    bs2.Center = fire.position;

                    if (bs.Intersects(bs2))

                    {

                        firefall.position = PrevPosition;

                    }

                }

            }

        }

private void MouseCheck(GameObject goods)

        {

            if (ms.LeftButton == ButtonState.Pressed)

            {

                Ray pickRay = GetPickRay();

                BoundingSphere bs = goods.model.Meshes[0].BoundingSphere;

                bs.Center = goods.position;

                Nullable<float> result = pickRay.Intersects(bs);

                if (result.HasValue == true && prevMouse.LeftButton == ButtonState.Released)

                {

                    goods.clickme = true;

                }

            }

            else if (ms.LeftButton == ButtonState.Released)

            {

                goods.clickme = false;

            }

        }

private void MouseControl(GameObject goods)

        {

            float Xpos = SetMouseMove(goods);

            if (goods.clickme)

            {

                if (ms.X > prevMouse.X)

                {

                    goods.position.X += (ms.X - prevMouse.X) / Xpos;

                }

                if (ms.X < prevMouse.X)

                {

                    goods.position.X -= (prevMouse.X - ms.X) / Xpos;

                }

                if (ms.Y < prevMouse.Y)

                {

                    goods.position.Y += (prevMouse.Y - ms.Y) / 3.5f;

                }

                if (ms.Y > prevMouse.Y)

                {

                    goods.position.Y -= (ms.Y - prevMouse.Y) / 3.5f;

                }

                if (ms.ScrollWheelValue - prevMouse.ScrollWheelValue > 0)

                {

                    goods.position.Z += 5.5f;

                }

                if (ms.ScrollWheelValue - prevMouse.ScrollWheelValue < 0)

                {

                    goods.position.Z -= 5.5f;

                }

            }

        }

private float SetMouseMove(GameObject goods)

        {

            if (goods.position.Z > 10.0f && goods.position.Z < 100.0f)

            {

                return 5.5f;

            }

            if (goods.position.Z < 10.0f && goods.position.Z > -10.0f)

            {

                return 4.5f;

            }

            if (goods.position.Z < -10.0f && goods.position.Z > -100.0f)

            {

                return 3.0f;

            }

 

            return 3.5f;

        }

private Ray GetPickRay()

        {

            MouseState mouseState = Mouse.GetState();

 

            int mouseX = mouseState.X;

            int mouseY = mouseState.Y;

 

            Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f);

            Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f);

 

            Matrix world = Matrix.CreateTranslation(0, 0, 0);

 

            Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearsource,

                cameraProjectionMatrix, cameraViewMatrix, world);

 

            Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farsource,

                cameraProjectionMatrix, cameraViewMatrix, world);

            Vector3 direction = farPoint - nearPoint;

            direction.Normalize();

            Ray pickRay = new Ray(nearPoint, direction);

 

            return pickRay;

        }

private void KeyboardCheck(GameObject goods)

        {

            KeyboardState key = Keyboard.GetState();

 

            if (key.IsKeyDown(Keys.Left))

            {

                goods.rotation.Y += 0.05f;

}

            if (key.IsKeyDown(Keys.Right))

            {

                goods.rotation.Y -= 0.05f;

            }

            if (key.IsKeyDown(Keys.Up))

            {

                goods.rotation.Z += 0.05f;

            }

            if (key.IsKeyDown(Keys.Down))

            {

                goods.rotation.Z -= 0.05f;

            }

            if (key.IsKeyDown(Keys.D))

            {

                goods.position.X += 5.5f;

            }

            if (key.IsKeyDown(Keys.A))

            {

                goods.position.X -= 5.5f;

            }

            if (key.IsKeyDown(Keys.W))

            {

                goods.position.Y += 5.5f;

            }

            if (key.IsKeyDown(Keys.S))

            {

                goods.position.Y -= 5.5f;

            }

            if (key.IsKeyDown(Keys.PageDown))

            {

                goods.position.Z += 5.5f;

            }

            if (key.IsKeyDown(Keys.PageUp))

            {

                goods.position.Z -= 5.5f;

            }

        }

rotected override void Draw(GameTime gameTime)

        {

            GraphicsDevice.Clear(Color.CornflowerBlue);

            // Alpha값을 사용하겠다는 선언

            GraphicsDevice.RenderState.BlendFunction = BlendFunction.Add;

            GraphicsDevice.RenderState.AlphaBlendEnable = true;

            GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;

            GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

            //**********************************//

            for (int i = 0; i < 5; i++)

            {

                DrawModel(obj[i]);

            }

 

            base.Draw(gameTime);

        }

private void DrawModel(GameObject gameobj)

        {

            foreach (ModelMesh mesh in gameobj.model.Meshes)

            {

                foreach (BasicEffect effect in mesh.Effects)

                {

                    effect.EnableDefaultLighting();

                    effect.PreferPerPixelLighting = true;

 

                    effect.World = Matrix.CreateFromYawPitchRoll(

                        gameobj.rotation.Y,

                        gameobj.rotation.X,

                        gameobj.rotation.Z) *

                        Matrix.CreateScale(gameobj.scale) *

                        Matrix.CreateTranslation(gameobj.position);

                    effect.Projection = cameraProjectionMatrix;

                    effect.View = cameraViewMatrix;

                    if (gameobj.clickme)

                    {

                        effect.Alpha = 0.5f;

                    }

                    else

                    {

                        effect.Alpha = 1.0f;

                    }

                }

                mesh.Draw();

            }

        }

 

마우스 컨트롤은 약간 조정했습니다.

: