1

I'm new to 3D programming and am having a terrible time getting my texture to fill my meshes properly. I've got it sizing correctly on the walls but the texture on the roof is running on an angle and is stretched out too far.

I have several methods to create the mesh but they are all eventually sent to AddTriangle method, where the TextureCoordinates are set.

public static void AddTriangle(this MeshGeometry3D mesh, Point3D[] pts)
{
    // Create the points.
    int index = mesh.Positions.Count;
    foreach (Point3D pt in pts)
    {
        mesh.Positions.Add(pt);
        mesh.TriangleIndices.Add(index++);
        mesh.TextureCoordinates.Add(new Point(pt.X + pt.Z, 0 - pt.Y));
    }
}

Here is how my material is set up.

imageBrush.ImageSource = new BitmapImage(new Uri("pack://application:,,,/Textures/shingles1.jpg"));
imageBrush.TileMode = TileMode.Tile;
imageBrush.ViewportUnits = BrushMappingMode.Absolute;
imageBrush.Viewport = new Rect(0, 0, 25, 25);
SidingColor = new DiffuseMaterial(imageBrush);
SidingColor.Color = RGB(89, 94, 100);

My texture looks like this:

shingle1.jpg

And here is the results I'm getting.

Texture Problem.jpg

That's as close as I could get after hours of fooling around and googling.

Neil B
  • 2,096
  • 1
  • 12
  • 23

1 Answers1

3

Whew that was a little more difficult than I anticipated.

Here are few resources that helped me find a solution.

How to convert a 3D point on a plane to UV coordinates?

From the link below I realized the above formula above formula was correct but for a right hand coordinate system. I converted it and that was the final step.

http://www.math.tau.ac.il/~dcor/Graphics/cg-slides/geom3d.pdf

Here is the code that works in case someone else has this question.

public static void AddTriangle(this MeshGeometry3D mesh, Point3D[] pts)
{
    if (pts.Count() != 3) return;

    //use the three point of the triangle to calculate the normal (angle of the surface)
    Vector3D normal = CalculateNormal(pts[0], pts[1], pts[2]);
    normal.Normalize();

    //calculate the uv products
    Vector3D u;
    if (normal.X == 0 && normal.Z == 0) u = new Vector3D(normal.Y, -normal.X, 0);
    else u = new Vector3D(normal.X, -normal.Z, 0);

    u.Normalize();
    Vector3D n = new Vector3D(normal.Z, normal.X, normal.Y);
    Vector3D v = Vector3D.CrossProduct(n, u);

    int index = mesh.Positions.Count;
    foreach (Point3D pt in pts)
    {
        //add the points to create the triangle
        mesh.Positions.Add(pt);
        mesh.TriangleIndices.Add(index++);

        //apply the uv texture positions
        double u_coor = Vector3D.DotProduct(u, new Vector3D(pt.Z,pt.X,pt.Y));
        double v_coor = Vector3D.DotProduct(v, new Vector3D(pt.Z, pt.X, pt.Y));
        mesh.TextureCoordinates.Add(new Point(u_coor, v_coor));            
    }
}

private static Vector3D CalculateNormal(Point3D firstPoint, Point3D secondPoint, Point3D thirdPoint)
{
    var u = new Point3D(firstPoint.X - secondPoint.X,
        firstPoint.Y - secondPoint.Y,
        firstPoint.Z - secondPoint.Z);

    var v = new Point3D(secondPoint.X - thirdPoint.X,
        secondPoint.Y - thirdPoint.Y,
        secondPoint.Z - thirdPoint.Z);

    return new Vector3D(u.Y * v.Z - u.Z * v.Y, u.Z * v.X - u.X * v.Z, u.X * v.Y - u.Y * v.X);
}
Neil B
  • 2,096
  • 1
  • 12
  • 23