public override void OnHandleInput() { Matrix xform = ghostObject.WorldTransform; Vector3 forwardDir = new Vector3(xform.M31, xform.M32, xform.M33); //Console.Write("forwardDir={0},{1},{2}\n", forwardDir[0], forwardDir[1], forwardDir[2]); Vector3 upDir = new Vector3(xform.M21, xform.M22, xform.M23); forwardDir.Normalize(); upDir.Normalize(); Vector3 pos = xform.Origin; Vector3 walkDirection = Vector3.Zero; const float walkVelocity = 1.1f * 4.0f; float walkSpeed = walkVelocity * FrameDelta * 10;// * 0.0001f; float turnSpeed = FrameDelta * 3; if (Input.KeysDown.Contains(Keys.Left)) { Matrix orn = xform; orn.Row4 = new Vector4(0, 0, 0, 1); orn *= Matrix.RotationAxis(upDir, -turnSpeed); orn.Row4 = new Vector4(pos.X, pos.Y, pos.Z, 1); ghostObject.WorldTransform = orn; } if (Input.KeysDown.Contains(Keys.Right)) { Matrix orn = xform; orn.Row4 = new Vector4(0, 0, 0, 1); orn *= Matrix.RotationAxis(upDir, turnSpeed); orn.Row4 = new Vector4(pos.X, pos.Y, pos.Z, 1); ghostObject.WorldTransform = orn; } if (Input.KeysDown.Contains(Keys.Up)) { walkDirection += forwardDir; } if (Input.KeysDown.Contains(Keys.Down)) { walkDirection -= forwardDir; } Vector3 cameraPos = pos - forwardDir * 12 + upDir * 5; //use the convex sweep test to find a safe position for the camera (not blocked by static geometry) SphereShape cameraSphere = new SphereShape(0.2f); ClosestConvexResultCallback cb = new ClosestConvexResultCallback(ref pos, ref cameraPos); cb.CollisionFilterMask = (short)CollisionFilterGroups.StaticFilter; Matrix posMatrix = Matrix.Translation(pos); Matrix cameraPosMatrix = Matrix.Translation(cameraPos); World.ConvexSweepTestRef(cameraSphere, ref posMatrix, ref cameraPosMatrix, cb); cameraSphere.Dispose(); if (cb.HasHit) { cameraPos = Vector3.Lerp(pos, cameraPos, cb.ClosestHitFraction); } cb.Dispose(); Freelook.SetEyeTarget(cameraPos, pos); character.SetWalkDirection(walkDirection * walkSpeed); base.OnHandleInput(); }