Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

So i'm trying to get terrain picking going.

I set up my ray, and I can pick out models, or sprites, whatever I want, no problem.

But when I try and get my 3D coords based off terrain collision it will only work when I'm facing forward. My map is 128 by 128 and I can lead my cursor all the way to 128X and -128Z but if I'm facing the opposite way then it seems I'm getting double the number.

I'm kinda noob, but I think somewhere I need to be setting some vector up with Math.Abs, is there something like this usually done in a standard camera class? I'm going to keep debugging but if anyone has ran into problems similar to this I'd love to know

Update: my code. Pretty standard, trying to learn from the docs online.

Defining basic mouse ray

 public void UpdateWorldCoords(TerrainObject terrain,Cameras.Camera camera)
    {
            Viewport viewport = Graphics.GraphicsManager.GraphicsDevice.Viewport;
            Vector3 nearSource = new Vector3(mouseCoords.X, mouseCoords.Y, 0);
            Vector3 farSource = new Vector3(mouseCoords.X, mouseCoords.Y, 1);

            Vector3 nearPoint = viewport.Unproject(nearSource, camera.Proj, camera.View, Matrix.Identity);
            Vector3 farPoint = viewport.Unproject(farSource, camera.Proj, camera.View, Matrix.Identity);

            Vector3 direction = nearPoint - farPoint;
            direction.Normalize();
            MouseRay = new Ray(nearPoint, direction);

            worldCoords = terrain.GetRayCollisionPoint(MouseRay);

}

Thats how I get my mouse ray and I can select objects with it a-ok! Next, theres a standard heightmap.

  public Vector3 GetRayCollisionPoint(Ray ray)
    {
        ray = ClipRay(ray, 0, 100);
        ray = LinearSearch(ray);
        Vector3 collisionPoint = BinarySearch(ray);
        //collisionPoint = BilliarInterpolation(collisionPoint);
        rayLine = new Line();
        rayLine.Points = new ColorPoint[]
        {
            LineBatch.CreateColorPoint(ray.Position,Color.Purple),
            LineBatch.CreateColorPoint(ray.Position+ray.Direction,Color.Black)
        };
        rayLine.Indices = new short[]{
            0,1
        };

        return collisionPoint;
  }
private Ray LinearSearch(Ray ray)
    {
        ray.Direction /= 50.0f;
        Vector3 nextPoint = ray.Position + ray.Direction;
        float heightAtNextPoint = BilliarInterpolation(new Vector3(nextPoint.X,0, nextPoint.Z)).Y;
        while (heightAtNextPoint < nextPoint.Y)
        {
            ray.Position = nextPoint;
            nextPoint = ray.Position + ray.Direction;
            heightAtNextPoint = BilliarInterpolation(new Vector3(nextPoint.X, 0, nextPoint.Z)).Y;
        }
        return ray;
    }
    private Vector3 BinarySearch(Ray ray)
    {
        float accuracy = 0.01f;
        float heightAtStartingPoint = BilliarInterpolation(new Vector3(ray.Position.X, 0, ray.Position.Z)).Y;
        float currentError = ray.Position.Y - heightAtStartingPoint;
        int counter = 0;
        while (currentError > accuracy)
        {
            ray.Direction /= 2.0f;
            Vector3 nextPoint = ray.Position + ray.Direction;
            float heightAtNextPoint = BilliarInterpolation(new Vector3(nextPoint.X, 0, nextPoint.Z)).Y;
            if (nextPoint.Y > heightAtNextPoint)
            {
                ray.Position = nextPoint;
                currentError = ray.Position.Y - heightAtNextPoint;
            }
            if (counter++ == 1000) break;
        }
        return ray.Position;
    }

And heres this for keeping things on correct height

  public Vector3 BilliarInterpolation(Vector3 position)
    {
        if (position.X > 0 && position.Z < 0)
        {
            int x0 = (int)MathHelper.Clamp(position.X, 0, width - 2);
            int y0 = (int)MathHelper.Clamp(-(int)position.Z, 0, height - 2);
            double dx = (double)MathHelper.Clamp(position.X - x0, 0, width);
            double dy = (double)MathHelper.Clamp(-position.Z - y0, 0, height);
            double omdx = (double)MathHelper.Clamp(1 - (float)dx, 0, width);
            double omdy = (double)MathHelper.Clamp(1 - (float)dy, 0, height);
            double bilinear = omdx * omdy * heightData[x0, y0] +
            omdx * dy * heightData[x0, y0 + 1] +
            dx * omdy * heightData[x0 + 1, y0] +
            dx * dy * heightData[x0 + 1, y0 + 1];

            position.Y = (float)bilinear;
        }
        return position;
    }
share|improve this question
    
Still debugging and really lost. I now draw the triangle I'm selecting. And it works perfectly all the way up and down if I'm facing postive on the x axis and negative on the z, but if they're flipped then their values get really crazy. –  Theodore Enderby Mar 30 '13 at 1:57
1  
Post your code. Your picking ray absolutely should change with your camera orientation. The ray is unprojected using the camera's view matrix, so the two will be strongly related. I say post your code because you are certainly doing something wrongly if you expect your ray to not change when the screenspace changes. But nobody can help without seeing that code. –  Seth Battin Mar 30 '13 at 6:12
    
Hey thanks for replying. I'm just going to start a fresh project with only Camera,Terrain, and picking and try and get some more accurate results. I have a visual rep of the ray and I can barely see it, so it must be working good. I've noticed that it all depends on my cameras pitch and yaw so maybe I'm mucking up something over there. But its strange that my object picking works perfect regardless of rotation. –  Theodore Enderby Mar 30 '13 at 6:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.